package com.cloudkinto.service.orderoutput.impl;

import cn.afterturn.easypoi.csv.entity.CsvExportParams;
import cn.afterturn.easypoi.entity.ImageEntity;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.DicBusinessConstant;
import com.cloudkinto.common.DicBusinessItemConstant;
import com.cloudkinto.common.common.DateFormater;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.*;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.extentity.OrderOutputYamatoSizeExcelExportDto;
import com.cloudkinto.extentity.output.OrderOutputProductRackDto;
import com.cloudkinto.extentity.stock.PickupStockRackDto;
import com.cloudkinto.service.company.CompanyService;
import com.cloudkinto.service.dic.DicBusinessItemService;
import com.cloudkinto.service.ecang.ECangService;
import com.cloudkinto.service.email.MailSenderService;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.finance.CostRecordService;
import com.cloudkinto.service.finance.vo.IdAndNameEntity;
import com.cloudkinto.service.operate.OperateRecordService;
import com.cloudkinto.service.operate.vo.OperateRes;
import com.cloudkinto.service.order.OrderAmazonService;
import com.cloudkinto.service.order.OrderRakutenService;
import com.cloudkinto.service.order.OrderShopifyService;
import com.cloudkinto.service.order.OrderYahooService;
import com.cloudkinto.service.order.vo.ShopifyShippingEneity;
import com.cloudkinto.service.order.vo.amazon.amazonorder.OrderFulfillment;
import com.cloudkinto.service.order.vo.rakuten.BasketidModelRequest;
import com.cloudkinto.service.order.vo.rakuten.OrderShippingModelRequest;
import com.cloudkinto.service.order.vo.rakuten.ShippingModelEntity;
import com.cloudkinto.service.order.vo.shopify.ShopifyRequestReq;
import com.cloudkinto.service.order.vo.yahoo.OrderShipStatusChangeReq;
import com.cloudkinto.service.orderback.OrderBackService;
import com.cloudkinto.service.orderback.vo.OrderBackAddItem;
import com.cloudkinto.service.orderback.vo.OrderBackAddReq;
import com.cloudkinto.service.orderinput.OrderInputService;
import com.cloudkinto.service.orderoutput.OrderOutputService;
import com.cloudkinto.service.orderoutput.vo.*;
import com.cloudkinto.service.orderoutput.vo.cutoff.CutOffReq;
import com.cloudkinto.service.orderqoo.OrderQoo10Service;
import com.cloudkinto.service.orderqoo.vo.Qoo10RequestReq;
import com.cloudkinto.service.product.ProductOutService;
import com.cloudkinto.service.product.ProductStockFlowingService;
import com.cloudkinto.service.product.vo.flowing.ProductStockFlowingRes;
import com.cloudkinto.service.product.vo.rack.SendRes;
import com.cloudkinto.service.region.JpRegionService;
import com.cloudkinto.service.replacement.ReplacementService;
import com.cloudkinto.service.shipprice.ShipPriceService;
import com.cloudkinto.service.shop.ShopService;
import com.cloudkinto.service.stock.StockLogService;
import com.cloudkinto.service.stock.StockPickUpService;
import com.cloudkinto.service.stock.StockRecordService;
import com.cloudkinto.service.stock.vo.UpdatePickUpReq;
import com.cloudkinto.service.stock.vo.record.StockRecordPageRes;
import com.cloudkinto.service.storage.StorageService;
import com.cloudkinto.service.track.TrackInfoService;
import com.cloudkinto.utils.BarCodeUtils;
import com.cloudkinto.utils.FreeMarkerUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.Session;
import javax.mail.Transport;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author 张永远
 * @since 2020-06-04
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)//事务回滚
public class OrderOutputServiceImpl extends ServiceImpl<OrderOutputDao, OrderOutputDo> implements OrderOutputService {
    private static final String SHIPMENT_TYPE_0 = "普通";
    private static final String SHIPMENT_TYPE_1 = "次日达";
    private static final String ORDER_OUTPUT_TYPE_2 = "FBA转运";
    private static final String ORDER_OUTPUT_TYPE_1 = "一件代发";
    public static final String SHOPIFY_PREFIX = "shopify_";
    private static final String ORDER_SKU_SUBTOTAL_CODE_KEY = "Order_Sku_subtotal_Code";
    @Autowired
    private OrderOutputDao dao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private OrderOutputPackageDao packageDao;
    @Autowired
    private OrderOutputProductDao productDao;
    @Autowired
    private OrderRakutenPackageDao rakutenPackageDao;
    @Autowired
    private OrderRakutenProductDao rakutenProductDao;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private StorageService storageService;
    @Autowired
    private JpRegionService regionService;
    @Autowired
    private ProductSkuMapDao productSkuMapDao;
    @Autowired
    private StorageDao storageDao;
    @Autowired
    private DicBusinessItemDao dicBusinessItemDao;
    @Autowired
    private ShipPriceService mShipPriceService;
    @Autowired
    private StockRecordDao mStockRecordDao;
    @Autowired
    private CompanyDao mCompanyDao;
    @Autowired
    private DimensDao mDimenDao;
    @Autowired
    private OrderRakutenDao orderRakutenDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private ShopService shopService;
    @Autowired
    private OperateRecordService operateRecordDao;
    @Autowired
    private StockLogService mStockLogService;
    @Autowired
    private CostRecordService mCostService;
    @Autowired
    private JpRegionService mRegionService;
    @Autowired
    private TrackInfoService mTrackService;

    @Autowired
    private OrderAmazonService mOrderAmazonService;
    @Autowired
    private OrderRakutenService orderRakutenService;
    @Autowired
    private OrderShopifyService orderShopifyService;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private OrderRakutenDao rakutenDao;
    @Autowired
    private OrderAmazonDao amazonDao;
    @Autowired
    private FileService fileService;
    @Autowired
    private OrderRakutenShippingDao rakutenShippingDao;
    @Autowired
    private FbaStorageDao fbaStorageDao;
    @Autowired
    private FbaDimensDao fbaDimensDao;
    @Autowired
    private FbaShipPriceDao fbaShipPriceDao;
    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private OrderAmazonDao orderAmazonDao;
    @Autowired
    private MailSenderService mailSenderService;
    @Autowired
    private OrderBackService orderBackService;
    @Autowired
    private TrackInfoDao mTrackDao;
    @Value("${gbc.template.filePath}")
    private String templatePath;
    @Value("${gbc.uploadPath.filePathLocal}")
    private String filePath;
    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;
    @Autowired
    private StorageServiceProjectDao storageServiceProjectDao;
    @Autowired
    private OrderShopifyDao shopifyDao;
    @Autowired
    private OrderShopifyShipDao orderShopifyShipDao;
    @Autowired
    private FbaOrderOutputDao fbaOrderOutDao;
    @Autowired
    private FbaOrderOutputPackageDao fbaOrderOutputPackageDao;
    @Autowired
    private FbaOrderOutputProductDao fbaOrderOutputProductDao;
    @Autowired
    private OrderInputService orderInputService;
    @Autowired
    private OrderWorkDao orderWorkDao;
    @Autowired
    private ReplacementDao replacementDao;
    @Autowired
    private OrderYahooService yahooService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderOutputSkuSubtotalDao subTotalDao;
    @Autowired
    private StockRecordService stockRecordService;
    @Autowired
    private OrderOutputPackageDetailDao packageDetailDao;
    @Autowired
    private ProductStockDao productStockDao;
    @Autowired
    private ProductStockRackDao productStockRackDao;
    @Autowired
    private StorageShelfDao storageShelfDao;
    @Autowired
    private StoragePositionDao storagePositionDao;
    @Autowired
    private StockPickUpDao stockPickUpDao;
    @Autowired
    private StockPickUpDetailDao stockPickUpDetailDao;
    @Autowired
    private ProductOutDao productOutDao;
    @Autowired
    private ProductOutService productOutService;
    @Autowired
    private ProductOutRecordDao productOutRecordDao;
    @Autowired
    private ProductStockFlowingDao productStockFlowingDao;
    @Autowired
    private ProductStockFlowingService productStockFlowingService;
    @Autowired
    private StockPickUpService stockPickUpService;
    @Autowired
    private ReplacementService replacementService;
    @Autowired
    private DicBusinessItemService dicBusinessItemService;
    @Autowired
    private ECangService ecangService;
    @Autowired
    private OrderQoo10Service orderQoo10Sercie;
    @Autowired
    private StockPickUpRuleDao stockPickUpRuleDao;
    @Autowired
    private OrderOutputProductDao orderOutputProductDao;


    @Override
    public SingleResult addInit(Long currentUserId, Long companyId) {
        Map map = new HashMap();
        map.put("storageList", storageService.getList(new HashMap<>()));
        map.put("regionList", regionService.getList(new HashMap<>()));
        map.put("shopList", shopService.selectShopListInit(currentUserId, companyId));
        LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.trackCompany);
        List<DicBusinessItemDo> trackCompanyList = dicBusinessItemDao.selectList(wrapper);
        List<IdAndNameEntity> trackList = new ArrayList<>();
        for (DicBusinessItemDo itemDo : trackCompanyList) {
            trackList.add(new IdAndNameEntity(itemDo.getId().intValue(), itemDo.getDicItemValue()));
        }

        map.put("trackList", trackList);

        List<Map> productTypeList = new ArrayList<>();
        LambdaQueryWrapper<DicBusinessItemDo> wrapperProductType = new LambdaQueryWrapper<>();
        wrapperProductType.eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.productType);
        List<DicBusinessItemDo> businessItemDoList = dicBusinessItemDao.selectList(wrapperProductType);
        if (!CollectionUtils.isEmpty(businessItemDoList)) {
            for (DicBusinessItemDo businessItemDo : businessItemDoList) {
                Map mapProductType = new HashMap();
                mapProductType.put("id", businessItemDo.getId());
                mapProductType.put("value", businessItemDo.getDicItemValue());
                productTypeList.add(mapProductType);
            }
        }
        map.put("productTypeList", productTypeList);

        map.put("companyTree", companyService.tree());
        return SingleResult.success(map);
    }

    @Override
    public String add(OrderOutputAddReq req, Long userId) {
        String value = addCheck(req);
        if (value != null) return value;
        OrderOutputDo entityDo = new OrderOutputDo();
        BeanUtils.copyProperties(req, entityDo);
        ShopDo shopDo = shopDao.selectById(req.getShopId());
        if (shopDo == null) {
            return StringsUtil.createI18Message(SysConstant.Shop_NotExist);
        }
        //判断是一单一件还是一单多件
        int count = 0;
        for (OrderOutputProductAddReq orderOutputProductAddReq : req.getPackageList().get(0).getProductList()) {
            count += orderOutputProductAddReq.getCount();
        }
        entityDo.setOrderType(count > 1 ? 2 : 1);

        entityDo.setCompanyId(shopDo.getCompanyId());
        if (StringUtils.isEmpty(req.getArea())) {
            JpRegionDo regionDo = regionService.getRegionDoByPostCode(req.getPostCode());
            if (regionDo != null) entityDo.setArea(regionDo.getName());
        }
//        if (req.getOrderType() == null) req.setOrderType(1);
        if (StringUtils.isNotBlank(req.getDeliveryDate()))
            entityDo.setDeliveryDate(TimeUtils.parseDate(req.getDeliveryDate()));
        handlerAddBefore(entityDo, userId);
        save(entityDo);
        value = handlerAddProduct(req.getPackageList().get(0).getProductList(), entityDo, userId);
        if (value != null) {
            dao.deleteById(entityDo.getId());
            return value;
        }
        handlerAddAfter(entityDo, req);
        //日志操作
        operateRecordDao.operateAddRecord(SysConstant.OPERATE_CREATE_ORDER, entityDo.getId(), userId, 3);
//        operateRecord("创建", entityDo.getId(), userId);

        return null;
    }

    @Override
    public SingleResult reissue(OrderOutputReissueReq req, Long userId) {
        OrderOutputDo orderOutputDo = dao.selectById(req.getId());
        orderOutputDo.setCreateBy(userId);
        orderOutputDo.setCreateTime(new Date());
        orderOutputDo.setUpdateBy(null);
        orderOutputDo.setUpdateTime(new Date());
        orderOutputDo.setStatus(DicBusinessItemConstant.outCreateState);
        orderOutputDo.setTrackId(null);
        orderOutputDo.setTrackNumber(null);
        orderOutputDo.setId(null);
        dao.insert(orderOutputDo);
        orderOutputDo.setOrderOutputNumber(OrderCodeUtil.getOrderOutNumber(orderOutputDo.getId()));

        OrderOutputPackageDo packageDo = new OrderOutputPackageDo();
        packageDo.setCreateBy(userId);
        packageDo.setOrderOutputId(orderOutputDo.getId());
        packageDo.setCreateTime(new Date());
        packageDao.insert(packageDo);
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder stringBuilder2 = new StringBuilder();
        for (OrderOutputReissueProductReq productReq : req.getProductReqList()) {
            ProductInfoDo productInfoDo = productInfoDao.selectById(productReq.getProductId());
            OrderOutputProductDo outputProductDo = new OrderOutputProductDo();
            outputProductDo.setProductId(productReq.getProductId());
            outputProductDo.setCount(productReq.getCount());
            outputProductDo.setPackageId(packageDo.getId());
            outputProductDo.setOrderId(packageDo.getOrderOutputId());
            outputProductDo.setCreateBy(userId);
            outputProductDo.setCreateTime(new Date());
            outputProductDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
            String productSku = "";
            ProductInfoDo productInfo = productInfoDao.selectById(outputProductDo.getProductId());
            if (productInfo != null) {
                productSku = productInfoDo.getCommoditySku();
            }
            verifyStock(orderOutputDo.getShopId(), orderOutputDo.getStorageId(), outputProductDo.getProductId(), outputProductDo.getCount(), productSku);
            productDao.insert(outputProductDo);
            if (stringBuilder.length() > 0) stringBuilder.append(",");
            stringBuilder.append(productSku);
            if (stringBuilder2.length() > 0) stringBuilder2.append(",");
            stringBuilder2.append(productInfo.getStorageSku());
        }
        // 产品数量过多时需要人工审核，状态改为-1
        if (req.getProductReqList().size() > SysConstant.OUTPUT_PRODUCT_SIZE_LIMIT) {
            orderOutputDo.setStatus(DicBusinessItemConstant.outCreateState);
        }
        orderOutputDo.setCommoditySku(stringBuilder.toString());
        orderOutputDo.setStorageSku(stringBuilder2.toString());
        updateById(orderOutputDo);

        //选择递公司
        updateTrackId(orderOutputDo);
        return null;
    }


    private void handlerFbaStorageAdd(OrderOutputDo entityDo, OrderOutputAddReq req, Long userId) {
        if (!CollectionUtils.isEmpty(req.getPackageList())) {
            for (OrderOutputPackageAddReq packageAddReq : req.getPackageList()) {
                OrderOutputPackageDo packageDo = new OrderOutputPackageDo();
                packageDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                packageDo.setCreateBy(userId);
                packageDo.setCreateTime(new Date());
                packageDo.setOrderOutputId(entityDo.getId());
                packageDo.setHeight(packageAddReq.getHeight());
                packageDo.setLength(packageAddReq.getLength());
                packageDo.setWeight(packageAddReq.getWeight());
                packageDo.setWidth(packageAddReq.getWidth());
                packageDo.setCount(packageAddReq.getPackageCount());
                packageDao.insert(packageDo);

                if (!CollectionUtils.isEmpty(packageAddReq.getProductList())) {
                    for (OrderOutputProductAddReq productAddReq : packageAddReq.getProductList()) {
                        ProductInfoDo productInfoDo = productInfoDao.selectById(productAddReq.getProductId());
                        if (productInfoDo == null) {
                            throw new BizException(SysConstant.Product_NotExist);
                        }
                        OrderOutputProductDo outputProductDo = new OrderOutputProductDo();
                        outputProductDo.setCount(productAddReq.getCount());
                        outputProductDo.setCreateTime(new Date());
                        outputProductDo.setCreateBy(userId);
                        outputProductDo.setOrderId(entityDo.getId());
                        outputProductDo.setPackageId(packageDo.getId());
                        outputProductDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                        outputProductDo.setProductId(productAddReq.getProductId());
                        verifyStock(entityDo.getShopId(), entityDo.getStorageId(), outputProductDo.getProductId(), outputProductDo.getCount(), productInfoDo.getCommoditySku());
                        productDao.insert(outputProductDo);
                    }
                }
            }

            updateFBATrackId(entityDo);
        }
    }


    private String handlerAddProduct(List<OrderOutputProductAddReq> orderProductList, OrderOutputDo entityDo, Long userId) {
        OrderOutputPackageDo packageDo = new OrderOutputPackageDo();
        packageDo.setCreateBy(userId);
        packageDo.setOrderOutputId(entityDo.getId());
        packageDo.setCreateTime(new Date());
        packageDao.insert(packageDo);
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder stringBuilder2 = new StringBuilder();
        if (entityDo.getStorageId() != null && 0 != entityDo.getStorageId()) {
            for (OrderOutputProductAddReq productReq : orderProductList) {
                if (productReq.getProductId() == 0)
                    return StringsUtil.createI18Message(SysConstant.Product_NotExist_Sku, productReq.getCommoditySku());
                ProductInfoDo productInfoDo = productInfoDao.selectById(productReq.getProductId());
                if (productInfoDo == null)
                    return StringsUtil.createI18Message(SysConstant.Product_NotExist_Sku, productReq.getCommoditySku());
                OrderOutputProductDo outputProductDo = new OrderOutputProductDo();
                outputProductDo.setSku(productReq.getCommoditySku());
                outputProductDo.setProductId(productReq.getProductId());
                outputProductDo.setCount(productReq.getCount());
                outputProductDo.setPackageId(packageDo.getId());
                outputProductDo.setOrderId(packageDo.getOrderOutputId());
                outputProductDo.setCreateBy(userId);
                outputProductDo.setCreateTime(new Date());
                outputProductDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                String productSku = "";
                ProductInfoDo productInfo = productInfoDao.selectById(outputProductDo.getProductId());
                if (productInfo != null) {
                    productSku = productInfoDo.getCommoditySku();
                }
                try {
                    verifyStock(entityDo.getShopId(), entityDo.getStorageId(), outputProductDo.getProductId(), outputProductDo.getCount(), productSku);
                } catch (BizException e) {
                    e.printStackTrace();
                    return StringsUtil.createI18Message(e.getMessage(), e.getArgs());
                }
                productDao.insert(outputProductDo);
                if (stringBuilder.length() > 0) stringBuilder.append(",");
                stringBuilder.append(productSku);
                if (stringBuilder2.length() > 0) stringBuilder2.append(",");
                stringBuilder2.append(productInfo.getStorageSku());
            }
        } else {//不指定仓库，系统自动选择
            List<OrderOutputProductAddReq> productAddReqList = orderProductList;
            List<OrderOutputProductAddReq> productAddReqUploadList = new ArrayList<>();
            long storageId = 0L;
            //自动分配仓库
            Long stateId = regionService.getStateIdByPostCode(entityDo.getPostCode());
            if (stateId <= 7L || stateId != 9L) {//大阪地区优先发货仓库
                storageId = 12L;
            } else if (stateId >= 8L) {//东京仓库优先发货仓库
                storageId = 10L;
            }
            long lastStorageId = storageId;
            for (OrderOutputProductAddReq productDo : productAddReqList) {//多个产品判断
                Long productId = getProductId(productDo.getCommoditySku(), entityDo.getCompanyId());
                ProductInfoDo productInfoDo = productInfoDao.selectById(productId);
                if (productId == null)
                    return (StringsUtil.createI18Message(SysConstant.OrderYahoo_Product_Notfound, entityDo.getOrderNo(), productDo.getCommoditySku()));
                try {
                    verifyStock(entityDo.getShopId(), storageId, productId, productDo.getCount(), productDo.getCommoditySku());
                    OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                    productDetail.setProductId(productId);
                    productDetail.setCount(productDo.getCount());
                    if (stringBuilder.length() > 0) stringBuilder.append(",");
                    stringBuilder.append(productDo.getCommoditySku());
                    if (stringBuilder2.length() > 0) stringBuilder2.append(",");
                    stringBuilder2.append(productInfoDo.getStorageSku());
                    productAddReqUploadList.add(productDetail);
                } catch (Exception e) {
                    e.printStackTrace();
                    storageId = 0;
                }

            }
            entityDo.setStorageId(storageId);
            //一个仓库是否发完所有订单
            if (storageId == 0) {
                List<OrderRakutenProductDo> productDoListFailed = new ArrayList<>();
                LambdaQueryWrapper<StorageDo> lambdaQueryWrapper = new LambdaQueryWrapper();
                lambdaQueryWrapper.eq(StorageDo::getSupportShip, 1).ne(StorageDo::getId, lastStorageId);
                if (stateId <= 7 || stateId != 9) {
                    lambdaQueryWrapper.orderByDesc(StorageDo::getStorageArea);
                } else {
                    lambdaQueryWrapper.orderByAsc(StorageDo::getStorageArea);
                }
                List<StorageDo> storageDos = storageDao.selectList(lambdaQueryWrapper);
                storageId = 0L;
                if (storageDos != null) {
                    kk:
                    for (StorageDo storageDo : storageDos) {
                        //遍历支持捆包仓库是否都有库存
                        for (OrderOutputProductAddReq productDo : productAddReqList) {//多个产品判断
                            Long productId = getProductId(productDo.getCommoditySku(), entityDo.getCompanyId());
                            ProductInfoDo productInfoDo = productInfoDao.selectById(productId);
                            if (productId == null)
                                return (StringsUtil.createI18Message(SysConstant.OrderYahoo_Product_Notfound, entityDo.getOrderNo(), productDo.getCommoditySku()));
                            try {
                                verifyStock(entityDo.getShopId(), storageDo.getId(), productId, productDo.getCount(), productDo.getCommoditySku());
                                OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                                productDetail.setProductId(productId);
                                productDetail.setCommoditySku(productDo.getCommoditySku());
                                productDetail.setCount(productDo.getCount());
                                if (stringBuilder.length() > 0) stringBuilder.append(",");
                                stringBuilder.append(productDo.getCommoditySku());
                                if (stringBuilder2.length() > 0) stringBuilder2.append(",");
                                stringBuilder2.append(productInfoDo.getStorageSku());
                                productAddReqUploadList.add(productDetail);
                            } catch (Exception e) {
                                e.printStackTrace();
                                storageId = 0;
                                productAddReqUploadList.clear();
                                continue kk;
                            }

                        }
                        storageId = storageDo.getId();
                        break kk;
                    }
                    entityDo.setStorageId(storageId);
                }
                if (storageId == 0) {//捆包仓库无库存，分别发
                    LambdaQueryWrapper<StorageDo> queryWrapper = new LambdaQueryWrapper();
                    List<OrderOutputProductAddReq> productAddReqUploadList1 = new ArrayList<>();
                    queryWrapper.eq(StorageDo::getCountryType, 1);
                    List<StorageDo> storageDoList = storageDao.selectList(queryWrapper);
                    StringBuilder stringBuilderNoStock = new StringBuilder();
                    for (OrderOutputProductAddReq productDo : productAddReqList) {
                        storageId = 0L;
                        double shipPirce = 99999D;
                        Long productId = getProductId(productDo.getCommoditySku(), entityDo.getCompanyId());
                        ProductInfoDo productInfoDo = productInfoDao.selectById(productId);

                        for (StorageDo storageDo : storageDoList) {//遍历仓库是否都有库存
                            LambdaQueryWrapper<StockRecordDo> wrapper2 = new LambdaQueryWrapper();
                            double[] size = mShipPriceService.countSameSkuSize(new double[4], productId, 1);
                            wrapper2.eq(StockRecordDo::getShopId, entityDo.getShopId()).eq(StockRecordDo::getProductInfoId, productId).eq(StockRecordDo::getStorageId, storageDo.getId());
                            StockRecordDo stockRecordDo1 = mStockRecordDao.selectOne(wrapper2);
                            int noDeliveredCount1 = mStockRecordDao.getOrderOutCount(productId, entityDo.getShopId(), storageDo.getId()) + mStockRecordDao.getOrderOutTurn2FbaCount(productId, entityDo.getShopId(), storageDo.getId());
                            if (stockRecordDo1 != null && stockRecordDo1.getCanSellCount() - noDeliveredCount1 > 0) {
                                List<ShipPriceDo> shipPriceDos = mShipPriceService.queryByRegionAndSize(entityDo.getPostCode(), size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], entityDo.getCod(), entityDo.getShipmentType(), storageDo.getId(), 1);
                                if (shipPriceDos.size() < 1 || shipPriceDos.get(0).getPrice() == 0) continue;
                                if (shipPirce > shipPriceDos.get(0).getPrice()) {//选择最便宜的价格
                                    shipPirce = shipPriceDos.get(0).getPrice();
                                    storageId = storageDo.getId();
                                }
                            }
                        }
                        if (storageId == 0) {
                            stringBuilderNoStock.append("(" + productDo.getCommoditySku() + ")");
                            continue;
                        }
                        OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                        productDetail.setProductId(productId);
                        productDetail.setCommoditySku(productDo.getCommoditySku());
                        productDetail.setCount(productDo.getCount());
                        productAddReqUploadList1.add(productDetail);
                        if (stringBuilder.length() > 0) stringBuilder.append(",");
                        stringBuilder.append(productDo.getCommoditySku());
                        if (stringBuilder2.length() > 0) stringBuilder2.append(",");
                        stringBuilder2.append(productInfoDo.getStorageSku());
                        OrderOutputDo orderOutputDoNew = new OrderOutputDo();
                        BeanUtils.copyProperties(entityDo, orderOutputDoNew);
                        orderOutputDoNew.setStorageId(storageId);
                        save(orderOutputDoNew);
                        orderOutputDoNew.setOrderOutputNumber(OrderCodeUtil.getOrderOutNumber(orderOutputDoNew.getId()));
                        orderOutputDoNew.setStorageSku(productDo.getStorageSku());
                        orderOutputDoNew.setCommoditySku(productDo.getCommoditySku());

//                        for (OrderOutputProductAddReq productInfoDo1 : productAddReqUploadList1) {
                        OrderOutputPackageDo packageDo1 = new OrderOutputPackageDo();
                        packageDo1.setOrderOutputId(orderOutputDoNew.getId());
                        packageDo1.setCreateBy(orderOutputDoNew.getCreateBy());
                        packageDo1.setCreateTime(new Date());
                        packageDo1.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                        packageDao.insert(packageDo1);
                        OrderOutputProductDo outputProductDo4 = new OrderOutputProductDo();
                        outputProductDo4.setProductId(productId);
                        productDetail.setCommoditySku(productDo.getCommoditySku());
                        outputProductDo4.setCount(productDo.getCount());
//        outputProductDo4.setCommoditySku(productInfoDo.getCommoditySku());
                        outputProductDo4.setOrderId(orderOutputDoNew.getId());
                        outputProductDo4.setPackageId(packageDo1.getId());
                        outputProductDo4.setCreateBy(orderOutputDoNew.getCreateBy());
                        outputProductDo4.setCreateTime(new Date());
                        outputProductDo4.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                        productDao.insert(outputProductDo4);
                        operateRecordDao.operateAddRecord(SysConstant.OPERATE_IMPORT_ORDER, entityDo.getId(), userId, 3);
//                        operateRecord("导入", orderOutputDoNew.getId(), orderOutputDoNew.getCreateBy());

//                        }
                        if (orderOutputDoNew.getStorageId() == 0) {
                            continue;
                        }
                        String value = updateTrackId(orderOutputDoNew);
                        if (value != null) {
                            return (value);
                        }
                    }
                    if (stringBuilderNoStock.length() > 0) {
                        return StringsUtil.createI18Message(SysConstant.OrderYahoo_Stock_NotEnough, entityDo.getOrderNo(), stringBuilderNoStock.toString());
                    }
                }
            } else {
                //第一个默认仓库能发货
            }
            if (productAddReqUploadList.size() < 1) {
                dao.deleteById(entityDo.getId());
                return StringsUtil.createI18Message(SysConstant.PRODUCT_NO);
            }
            for (OrderOutputProductAddReq productInfoDo : productAddReqUploadList) {
                OrderOutputProductDo outputProductDo4 = new OrderOutputProductDo();
                outputProductDo4.setProductId(productInfoDo.getProductId());
                outputProductDo4.setSku(productInfoDo.getCommoditySku());
                outputProductDo4.setCount(productInfoDo.getCount());
//        outputProductDo4.setCommoditySku(productInfoDo.getCommoditySku());
                outputProductDo4.setOrderId(entityDo.getId());
                outputProductDo4.setPackageId(packageDo.getId());
                outputProductDo4.setCreateBy(entityDo.getCreateBy());
                outputProductDo4.setCreateTime(new Date());
                outputProductDo4.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                productDao.insert(outputProductDo4);
            }
        }
        // 产品数量过多时需要人工审核，状态改为-1
        if (orderProductList.size() > SysConstant.OUTPUT_PRODUCT_SIZE_LIMIT) {
            entityDo.setStatus(DicBusinessItemConstant.outCreateState);
        }
//        operateRecord("导入", entityDo.getId(), entityDo.getCreateBy());
        entityDo.setOrderOutputNumber(OrderCodeUtil.getOrderOutNumber(entityDo.getId()));
        entityDo.setStorageSku(stringBuilder2.toString());
        entityDo.setCommoditySku(stringBuilder.toString());
        String value = updateTrackId(entityDo);
        if (value != null) {
            return StringsUtil.createI18Message(SysConstant.ORDER_PLS_MANUAL, entityDo.getOrderNo(), value);
        }
        return null;
    }

    /**
     * 验证库存
     *
     * @param shopId
     * @param storageId
     * @param productId
     * @param count
     * @param commoditySku
     */
    private void verifyStock(Long shopId, Long storageId, Long productId, int count, String commoditySku) {
        LambdaQueryWrapper<StockRecordDo> wrapper = new LambdaQueryWrapper();
//            sendOutEntity.getCommoditySku(), sendOutEntity.getShopId(), sendOutEntity.getStorageId()
        wrapper.eq(StockRecordDo::getShopId, shopId).eq(StockRecordDo::getStorageId, storageId).eq(StockRecordDo::getProductInfoId, productId);
        StockRecordDo recordBean = mStockRecordDao.selectOne(wrapper);
        int waitCount = mStockRecordDao.getOrderOutCount(productId, shopId, storageId) + mStockRecordDao.getOrderOutTurn2FbaCount(productId, shopId, storageId);
        if (recordBean == null || recordBean.getCanSellCount() < 1 || recordBean.getCanSellCount() - waitCount < count) {
            Long product = getSubProductId(commoditySku, shopDao.selectById(shopId).getCompanyId());
            wrapper.eq(StockRecordDo::getProductInfoId, product);
            recordBean = mStockRecordDao.selectOne(wrapper);
            if (recordBean == null || recordBean.getCanSellCount() < 1 || recordBean.getCanSellCount() - waitCount < count) {
                throw new BizException(SysConstant.Product_Stock_NotEnough_Sku, commoditySku);
            }
        }
    }

    private Long getSubProductId(String sellerSku, Long companyId) {
        QueryWrapper skuWrapper = new QueryWrapper();
        skuWrapper.eq("sub_sku", sellerSku);
        skuWrapper.eq("company_id", companyId);
        ProductSkuMapDo productSkuMapDo = productSkuMapDao.selectOne(skuWrapper);
        if (productSkuMapDo == null) return 0L;
        return productSkuMapDo.getProductInfoId();
    }

    //新增校验
    private String addCheck(OrderOutputAddReq req) {
        if (!StringUtils.isNotBlank(req.getPostCode())) {
            return StringsUtil.createI18Message(SysConstant.OrderOutput_Check_PostCode);
        } else if (req.getPostCode().length() != 7) {
            if ((req.getPostCode().contains("-") && req.getPostCode().length() == 8)) {
            } else {
                return StringsUtil.createI18Message(SysConstant.OrderOutput_Check_CodeForm);
            }
        }
        req.setPostCode(req.getPostCode().trim().replaceAll("\\\"", ""));
        if (!StringUtils.isNotBlank(req.getAddress())) {
            return StringsUtil.createI18Message(SysConstant.OrderOutput_Check_Address);
        }
        req.setAddress(req.getAddress().trim().replaceAll("\\\"", ""));
        if (!StringUtils.isNotBlank(req.getOrderNo())) {
            return StringsUtil.createI18Message(SysConstant.OrderOutput_Check_OrderNo);
        }
        if (req.getShopId() == null) {
            return StringsUtil.createI18Message(SysConstant.Order_No_Shop);
        }
//        if (req.getStorageId() == null) throw new BizException("缺少仓库");
        if (req.getPackageList() == null || req.getPackageList().size() < 1) {
            return StringsUtil.createI18Message(SysConstant.Order_No_Product);
        }
        if ("-".equals(req.getDeliveryTime())) {
            req.setDeliveryTime(null);
        }
        String value = checkOrderNo(req.getOrderNo().trim(), req.getCompanyId());
        if (value != null) {
            return StringsUtil.createI18Message(value);
        }
        return null;
    }


    private String checkOrderNo(String orderNo, Long companyId) {
        LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderOutputDo::getOrderNo, orderNo).ge(OrderOutputDo::getSendDate, TimeUtils.getCurrentDateFormat(-30)).eq(OrderOutputDo::getCompanyId, companyId);
        Integer list = baseMapper.selectCount(wrapper);
        if (list < 1) {
            return null;
        } else {
            return StringsUtil.createI18Message(SysConstant.Order_Exist_0, orderNo);
        }
    }


    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(OrderOutputDo entityDo, Long userId) {
        entityDo.setCreateBy(userId);
        entityDo.setCreateTime(new Date());
        entityDo.setSendDate(new Date());
        entityDo.setStatus(DicBusinessItemConstant.outCreateState);
        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
    }

    //将新增的do转换成要返回的实体
    private String handlerAddAfter(OrderOutputDo entityDo, OrderOutputAddReq req) {
        entityDo.setOrderOutputNumber(OrderCodeUtil.getOrderOutNumber(entityDo.getId()));
        //todo 判断组装尺寸
        updateTrackId(entityDo);
        return null;
    }

    @Override
    public SingleResult updateInit(Long id) {
        Map<String, Object> map = new HashMap<>();
        map.put("storage", storageService.getList(new HashMap<>()));
        map.put("region", regionService.getList(new HashMap<>()));
        HashMap<String, String> map1 = new HashMap<>();
        OrderOutputDo outputDo = dao.selectById(id);
        map1.put("companyId", outputDo.getCompanyId() + "");
        map.put("shopList", shopService.getList(map1).stream().map(shopPageRes -> new IdAndNameEntity(shopPageRes.getId().intValue(), shopPageRes.getShopName())).collect(Collectors.toList()));
//        LambdaQueryWrapper<StockRecordDo> productInfoWrapper = new LambdaQueryWrapper<>();
//        productInfoWrapper.eq(StockRecordDo::getCompanyId, outputDo.getCompanyId());
//        productInfoWrapper.eq(StockRecordDo::getStorageId, outputDo.getStorageId());
//        productInfoWrapper.eq(StockRecordDo::getShopId, outputDo.getShopId());
//        List<StockRecordDo> stockRecordDos = mStockRecordDao.selectList(productInfoWrapper);
//        List<IdAndNameEntity> productSkuList = new ArrayList<>();
//        for (StockRecordDo stockRecordDo : stockRecordDos) {
//            ProductInfoDo productInfoDo = productInfoDao.selectById(stockRecordDo.getProductInfoId());
//            if (productInfoDo == null) continue;
//            productSkuList.add(new IdAndNameEntity(productInfoDo.getId().intValue(), productInfoDo.getCommoditySku()));
//        }
//        map.put("productSku", productSkuList);
        OrderOutputDetailRes detailRes = detail(id);
        map.put("detail", detailRes);
        return SingleResult.success(map);
    }

    public int getOrderType(List<OrderOutputProductDetail> productList) {
        int count = 0;
        for (OrderOutputProductDetail orderOutputProductAddReq : productList) {
            count += orderOutputProductAddReq.getCount();
        }
        return (count > 1 ? 2 : 1);
    }

    @Override
    public OrderOutputUpdateReq update(OrderOutputUpdateReq req, Long userId) {
        updateCheck(req);
        OrderOutputDo entityDo = dao.selectById(req.getId());
//        if (entityDo.getStatus() >= DicBusinessItemConstant.outWaitSendOut) {
//            throw new BizException("仓库已处理，请联系仓库修改订单信息");
//        }
        if (req.getFileId() != null) {
            fileService.deleteFile(entityDo.getFileId());
            fileService.uploadFile2(req.getFileId(), entityDo.getFileId());
        }
        BeanUtils.copyProperties(req, entityDo);
        if (StringUtils.isNotBlank(req.getDeliveryDate())) {
            entityDo.setDeliveryDate(TimeUtils.parseDate(req.getDeliveryDate()));
        } else {
            entityDo.setDeliveryDate(null);
        }
        entityDo.setOrderType(this.getOrderType(req.getPackageList().get(0).getProductList()));

        handlerUpdateBefore(entityDo, userId);

        //日志操作
        operateRecordDao.operateAddRecord(SysConstant.OPERATE_UPDATE_ORDER, entityDo.getId(), userId, 3);

//        operateRecord("修改", entityDo.getId(), userId);
        handlerUpdateAfter(req, entityDo);
        dao.updateById(entityDo);
//        updateTrackId(entityDo);
        return req;
    }
//
//    private void operateRecord(String operateStr, Long id, Long userId) {
//        operateRecord2(operateStr + "了出库订单", id, userId);
//    }

//    private void operateRecord2(String operateStr, Long id, Long userId) {
//        OrderOutputDo et = dao.selectById(id);
//        OperateRecordDo operateRecordDo = new OperateRecordDo();
//        operateRecordDo.setDeleteFlag(0);
//        operateRecordDo.setThirdId(id);
//        operateRecordDo.setType(3);
//        operateRecordDo.setOperateBy(userId);
//        operateRecordDo.setOperateTime(new Date());
//        operateRecordDo.setContent(operateStr);
//        operateRecordDo.setRemarks(JSON.toJSONString(et));
//        operateRecordDao.operateAddRecordAndValue(operateRecordDo);
//    }

    @Override
    public void cutoff(Long id, Long userId) {
        CutOffReq req = new CutOffReq();
        //ecang 变成截单中
        req.setId(id);
        req.setRecovered(false);
        this.cutoff(req, userId);
    }

    @Override
    public void cutoff(CutOffReq req, Long userId) {
        OrderOutputDo entityDo = dao.selectById(req.getId());
        if (entityDo == null || req.getRecovered() == null) {
            throw new BizException(SysConstant.No_Data);
        }

        //已审核状态不收取费用 库内截单300日币/单；已出库截单800日币/单；未成功，不收取费用
        if (DicBusinessItemConstant.outCreateCheckState.equals(entityDo.getStatus())) {
            //已审核 不收取费用
            entityDo.setStatus(DicBusinessItemConstant.orderCutOff);
//            entityDo.setCutFee(SysConstant.Cut_Fee_CheckStatus);
            if (req.getRecovered()) {
                //已追回
                entityDo.setStatus(DicBusinessItemConstant.outOrderBack);
            }
            dao.updateById(entityDo);
            operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_ORDER, entityDo.getId(), userId, 3);
            if (req.getRecovered()) {
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_BACK_ORDER, entityDo.getId(), userId, 3);
            }
        } else if (entityDo.getStatus() >= DicBusinessItemConstant.outSendOut && entityDo.getStatus() <= DicBusinessItemConstant.outException) {
            //已发货截单 不操作库存 只改状态
            entityDo.setStatus(DicBusinessItemConstant.orderCutOff);
//            entityDo.setCutFee(SysConstant.Cut_Fee_AfterSend);
            if (req.getRecovered()) {
                //已追回
                entityDo.setStatus(DicBusinessItemConstant.outOrderBack);
            }
            dao.updateById(entityDo);
            operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_ORDER, entityDo.getId(), userId, 3);
            if (req.getRecovered()) {
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_BACK_ORDER, entityDo.getId(), userId, 3);
                //扣费
                mCostService.add(0, entityDo.getOrderOutputNumber() + "截单费", entityDo.getCutFee(), entityDo.getShopId(), entityDo.getCompanyId(), entityDo.getId());
            }

        } else if (entityDo.getStatus().equals(DicBusinessItemConstant.outOrderBack) || entityDo.getStatus().equals(DicBusinessItemConstant.orderCutOff)) {
            //已追回 接单中不操作
            return;
        } else if (entityDo.getStatus().equals(DicBusinessItemConstant.alreadyPickUp) || entityDo.getStatus().equals(DicBusinessItemConstant.waitingPickUp) || entityDo.getStatus().equals(DicBusinessItemConstant.outWaitSendOut) || entityDo.getStatus().equals(DicBusinessItemConstant.outToCheck)
//                ||  ((entityDo.getStatus().equals(DicBusinessItemConstant.outWaitSendOut) ||
//                        entityDo.getStatus().equals(DicBusinessItemConstant.outToCheck)) && entityDo.getPickUpId() != null && entityDo.getPickUpId() != 0)
        ) {
            //未发货截单 需要操作库存
            //先去回滚库存，在去改状态
            if (req.getRecovered()) {
                this.rollStockForCutOff(entityDo, userId);
            }
            entityDo.setStatus(DicBusinessItemConstant.orderCutOff);
//            entityDo.setCutFee(SysConstant.Cut_Fee_BeforeSend);
            if (req.getRecovered()) {
                //已追回
                entityDo.setStatus(DicBusinessItemConstant.outOrderBack);
            }
            dao.updateById(entityDo);
            operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_ORDER, entityDo.getId(), userId, 3);
            if (req.getRecovered()) {
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_BACK_ORDER, entityDo.getId(), userId, 3);
                //扣费
                mCostService.add(0, entityDo.getOrderOutputNumber() + "截单费", entityDo.getCutFee(), entityDo.getShopId(), entityDo.getCompanyId(), entityDo.getId());
            }
        }
    }

    @Override
    public void finishCutOff(Long id, Long userId) {
        OrderOutputDo entityDo = dao.selectById(id);
        if (entityDo == null) {
            throw new BizException(SysConstant.No_Data);
        }
        if (!DicBusinessItemConstant.orderCutOff.equals(entityDo.getStatus())) {
            throw new BizException(SysConstant.Status_Error);
        }
        //判断是发货前截单还是 发货后截单
        if (entityDo.getSendTime() == null) {
            //发货前截单
            this.rollStockForCutOff(entityDo, userId);
            entityDo.setCutFee(SysConstant.Cut_Fee_BeforeSend);
        } else {
            entityDo.setCutFee(SysConstant.Cut_Fee_AfterSend);
        }
        entityDo.setStatus(DicBusinessItemConstant.outOrderBack);
        dao.updateById(entityDo);
        operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_BACK_ORDER, entityDo.getId(), userId, 3);
        //扣费
        if (entityDo.getCutFee() != 0d) {
            mCostService.add(0, entityDo.getOrderOutputNumber() + "截单费", entityDo.getCutFee(), entityDo.getShopId(), entityDo.getCompanyId(), entityDo.getId());
        }
    }

    public void rollStockForCutOff(OrderOutputDo entityDo, Long userId) {
        //删除库存之前要 先看看有没有绑定拣货单
        if (entityDo.getPickUpId() != null) {
            StockPickUpDo pickUpDo = stockPickUpDao.selectById(entityDo.getPickUpId());
            if (pickUpDo != null) {
                List<StockPickUpDetailDo> pickUpDetailDoList = stockPickUpDetailDao.selectList(new LambdaQueryWrapper<StockPickUpDetailDo>().eq(StockPickUpDetailDo::getPickUpId, pickUpDo.getId()).eq(StockPickUpDetailDo::getOrderOutputId, entityDo.getId()));
                for (StockPickUpDetailDo pickUpDetailDo : pickUpDetailDoList) {
                    if (DicBusinessItemConstant.orderCutOff.equals(entityDo.getStatus()) || DicBusinessItemConstant.alreadyPickUp.equals(entityDo.getStatus()) || DicBusinessItemConstant.waitingPickUp.equals(entityDo.getStatus()) || DicBusinessItemConstant.outToCheck.equals(entityDo.getStatus()) || DicBusinessItemConstant.outWaitSendOut.equals(entityDo.getStatus())) {
                        //解决 两个出库单 同时锁定一个库存id时，后者多的一个出库单先发货，将锁定库存发完，导致锁定库存不够
                        int goodQuantity = pickUpDetailDo.getNumber();
                        List<ProductStockRackDo> stockRackDoList;
                        ProductStockRackDo stockRackDo;
                        synchronized (this) {
                            stockRackDo = productStockRackDao.getOne(pickUpDetailDo.getStockRackId());
                            stockRackDoList = productStockRackDao.getLockingStockList(pickUpDetailDo.getProductId(), pickUpDo.getStorageId(), stockRackDo.getRackId());
                        }
                        if (stockRackDoList.stream().mapToInt(ProductStockRackDo::getGoodLockQuantity).sum() < goodQuantity) {
                            throw new BizException(SysConstant.Order_LockCount_NotEnough);
                        }
                        for (ProductStockRackDo rackDo : stockRackDoList) {
                            int onceCount = 0;
                            if (rackDo.getGoodLockQuantity() >= goodQuantity) {
                                onceCount = goodQuantity;
                                rackDo.setGoodLockQuantity(rackDo.getGoodLockQuantity() - goodQuantity);
                                rackDo.setGoodQuantity(rackDo.getGoodQuantity() + goodQuantity);
                                goodQuantity = 0;
                            } else {
                                onceCount = rackDo.getGoodLockQuantity();
                                goodQuantity -= rackDo.getGoodLockQuantity();
                                rackDo.setGoodLockQuantity(0);
                                rackDo.setGoodQuantity(rackDo.getGoodQuantity() + onceCount);
                            }
                            productStockRackDao.updateById(rackDo);
                            if (goodQuantity <= 0) {
                                break;
                            }
                        }
                        if (goodQuantity > 0) {
                            throw new BizException(SysConstant.Order_LockCount_NotEnough);
                        }
                        //库存流水新
                        productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.ReleaseLock.getValue(), entityDo.getOrderOutputNumber(), entityDo.getShopId(), pickUpDetailDo.getProductId(), pickUpDo.getStorageId(), pickUpDetailDo.getNumber(), 0, -pickUpDetailDo.getNumber(), stockRackDo.getRackId(), entityDo.getCompanyId(), userId, "出库单截单，释放锁定库存");
                    }
                    stockPickUpDetailDao.deleteById(pickUpDetailDo.getId());
                }
                //判断拣货单要不要删除
                List<StockPickUpDetailDo> list = stockPickUpDetailDao.selectList(new LambdaQueryWrapper<StockPickUpDetailDo>().eq(StockPickUpDetailDo::getPickUpId, pickUpDo.getId()));
                if (list.size() == 0) {
                    stockPickUpDao.deleteById(pickUpDo);
                }
            }
        }
    }

    private void handlerOrderBack(OrderOutputDo entityDo, Long userId, Long companyId) {

        OrderBackAddReq req = new OrderBackAddReq();
        req.setContactName(entityDo.getReceiverName());
        DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(entityDo.getTrackId());
        if (businessItemDo != null) {
            req.setTrackName(businessItemDo.getDicItemValue());
        }
        req.setOperateFee(entityDo.getOperateFee());
        req.setCompanyId(entityDo.getCompanyId());
        req.setOrderOutNumber(entityDo.getOrderOutputNumber());
        req.setShipFee(entityDo.getShipFee());
        req.setShopId(entityDo.getShopId());
        req.setStorageId(entityDo.getStorageId());
        req.setTaxFee(entityDo.getTaxFee());
        req.setTelPhone(entityDo.getTelPhone());
        req.setTrackNumber(entityDo.getTrackNumber());

        List<OrderBackAddItem> items = new ArrayList<>();
        LambdaQueryWrapper<OrderOutputProductDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderOutputProductDo::getOrderId, entityDo.getId());
        List<OrderOutputProductDo> orderOutputProductDoList = productDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(orderOutputProductDoList)) {
            for (OrderOutputProductDo orderOutputProductDo : orderOutputProductDoList) {
                OrderBackAddItem item = new OrderBackAddItem();
                item.setCount(orderOutputProductDo.getCount());
                item.setProductId(orderOutputProductDo.getProductId());
                items.add(item);
            }
        }
        req.setItems(items);

        orderBackService.add(req, userId, companyId);
    }

    //编辑校验
    private void updateCheck(OrderOutputUpdateReq req) {
        if (req.getPackageList() == null || req.getPackageList().size() < 1) {
            throw new BizException(SysConstant.Order_No_Product);
        }
    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(OrderOutputDo entityDo, Long userId) {
        entityDo.setUpdateBy(userId);
        entityDo.setUpdateTime(new Date());
    }

    //做修改之后要执行的业务定制处理
    private OrderOutputUpdateReq handlerUpdateAfter(OrderOutputUpdateReq updateReq, OrderOutputDo entityDo) {
        //已打单之后不允许修改商品信息
        if (!(DicBusinessItemConstant.outCreateState.equals(entityDo.getStatus()) || DicBusinessItemConstant.outCreateCheckState.equals(entityDo.getStatus()) || (DicBusinessItemConstant.outWaitSendOut.equals(entityDo.getStatus()) && entityDo.getPickUpId() == null))) {
            return updateReq;
        }
        //改版 出库管理 编辑可新增 删除 包裹
        List<Long> leftPackageIds = updateReq.getPackageList().stream().map(OrderOutputPackageUpdateReq::getId).filter(Objects::nonNull).collect(Collectors.toList());
        //先查出 旧包裹
        List<OrderOutputPackageDo> oldPackageList = packageDao.selectList(new LambdaQueryWrapper<OrderOutputPackageDo>().eq(OrderOutputPackageDo::getOrderOutputId, entityDo.getId()));
        //删除 不存在的包裹
        for (int i = 0; i < oldPackageList.size(); i++) {
            if (!leftPackageIds.contains(oldPackageList.get(i).getId())) {
                //删除该包裹 和包裹下的产品
                productDao.delete(new LambdaQueryWrapper<OrderOutputProductDo>().eq(OrderOutputProductDo::getPackageId, oldPackageList.get(i).getId()));
                packageDao.deleteById(oldPackageList.get(i).getId());
                oldPackageList.remove(i);
                i--;
            }
        }

        List<OrderOutputPackageUpdateReq> packageUpdateReqs = updateReq.getPackageList();
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder stringBuilder2 = new StringBuilder();
        for (OrderOutputPackageUpdateReq req : packageUpdateReqs) {
            OrderOutputPackageDo packageDo;
            if (req.getId() == null) {
                //说明是新增
                packageDo = new OrderOutputPackageDo();
                BeanUtils.copyProperties(req, packageDo);
                packageDo.setOrderOutputId(entityDo.getId());
                packageDao.insert(packageDo);

            } else {
                //编辑
                packageDo = packageDao.selectById(req.getId());
                if (packageDo == null) {
                    throw new BizException(SysConstant.OrderInput_Package_NotExist);
                }
                BeanUtils.copyProperties(req, packageDo);
                packageDao.updateById(packageDo);

                productDao.delete(new LambdaQueryWrapper<OrderOutputProductDo>().eq(OrderOutputProductDo::getPackageId, req.getId()));
            }
            //处理 产品信息
            this.insertProduct(req.getProductList(), packageDo.getId(), entityDo.getId(), updateReq.getShopId(), updateReq.getStorageId(), stringBuilder, stringBuilder2);
        }
        entityDo.setCommoditySku(stringBuilder.toString());
        entityDo.setStorageSku(stringBuilder2.toString());
        return updateReq;
    }

    public void insertProduct(List<OrderOutputProductDetail> productList, Long packageId, Long orderId, Long shopId, Long storageId, StringBuilder stringBuilder, StringBuilder stringBuilder2) {
        for (OrderOutputProductDetail product : productList) {
            ProductInfoDo productInfoDo = productInfoDao.selectById(product.getProductId());
            String commoditySKu = product.getCommoditySku();
            if (productInfoDo != null) commoditySKu = productInfoDo.getCommoditySku();
            OrderOutputProductDo productDo = new OrderOutputProductDo();
            BeanUtils.copyProperties(product, productDo);
            productDo.setPackageId(packageId);
            productDo.setSku(product.getCommoditySku());
            productDo.setCreateTime(new Date());
            productDo.setUpdateTime(new Date());
            productDo.setOrderId(orderId);
            verifyStock(shopId, storageId, product.getProductId(), product.getCount(), commoditySKu);
            productDao.insert(productDo);
            if (stringBuilder.length() > 0) {
                stringBuilder.append(",");
            }
            stringBuilder.append(commoditySKu);

            if (stringBuilder2.length() > 0) {
                stringBuilder2.append(",");
            }
            stringBuilder2.append(product.getStorageSku());
        }
    }

    @Override
    public int delete(Long id, Long userId) {
        OrderOutputDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);

        //删除库存之前要 先看看有没有绑定拣货单
        if (entityDo.getPickUpId() != null) {
            StockPickUpDo pickUpDo = stockPickUpDao.selectById(entityDo.getPickUpId());
            if (pickUpDo != null) {
                List<StockPickUpDetailDo> pickUpDetailDoList = stockPickUpDetailDao.selectList(new LambdaQueryWrapper<StockPickUpDetailDo>().eq(StockPickUpDetailDo::getPickUpId, pickUpDo.getId()).eq(StockPickUpDetailDo::getOrderOutputId, id));
                for (StockPickUpDetailDo pickUpDetailDo : pickUpDetailDoList) {
                    if (DicBusinessItemConstant.alreadyPickUp.equals(entityDo.getStatus()) || DicBusinessItemConstant.waitingPickUp.equals(entityDo.getStatus()) || DicBusinessItemConstant.outToCheck.equals(entityDo.getStatus()) || DicBusinessItemConstant.outWaitSendOut.equals(entityDo.getStatus())) {
                        //已拣货 需要释放 锁定库存
                        ProductStockRackDo rackDo = productStockRackDao.selectById(pickUpDetailDo.getStockRackId());
                        if (rackDo == null) {
                            throw new BizException(SysConstant.StockRack_NotExist);
                        }
                        if (rackDo.getGoodLockQuantity() < pickUpDetailDo.getNumber()) {
                            throw new BizException(SysConstant.StockRack_LockNotEnough);
                        }
                        rackDo.setGoodLockQuantity(rackDo.getGoodLockQuantity() - pickUpDetailDo.getNumber());
                        rackDo.setGoodQuantity(rackDo.getGoodQuantity() + pickUpDetailDo.getNumber());
                        productStockRackDao.updateById(rackDo);

                        //库存流水新
                        productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.ReleaseLock.getValue(), entityDo.getShopId(), pickUpDetailDo.getProductId(), pickUpDo.getStorageId(), pickUpDetailDo.getNumber(), 0, -pickUpDetailDo.getNumber(), rackDo.getRackId(), entityDo.getCompanyId(), userId, "出库单删除，释放锁定库存");

                    }
                    stockPickUpDetailDao.deleteById(pickUpDetailDo.getId());
                }
                //判断拣货单要不要删除
                List<StockPickUpDetailDo> list = stockPickUpDetailDao.selectList(new LambdaQueryWrapper<StockPickUpDetailDo>().eq(StockPickUpDetailDo::getPickUpId, pickUpDo.getId()));
                if (list.size() == 0) {
                    stockPickUpDao.deleteById(pickUpDo);
                }
            }
        }

        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(OrderOutputDo entityDo, Long userId) {
        entityDo.setDeleteBy(userId);
        entityDo.setDeleteTime(new Date());
        updateById(entityDo);
    }

    @Override
    public OrderOutputDetailRes detail(Long id) {
        OrderOutputDo entityDo = dao.selectById(id);
        OrderOutputDetailRes res = new OrderOutputDetailRes();
        if (entityDo == null) {
            throw new BizException(SysConstant.Order_NotExist1);
        }
        BeanUtils.copyProperties(entityDo, res);
        res.setFileUrl(fileService.getFilePath(entityDo.getFileId()));
        res.setSendList(this.getSendMsg(entityDo.getOrderOutputNumber()));
        //拣货单状态
        if (entityDo.getPickUpId() != null) {
            //有管理拣货单
            res.setPickStatus(1);
        } else {
            res.setPickStatus(0);
        }

        return handlerDetailAfter(entityDo, res);
    }

    /**
     * 获取发货记录
     *
     * @param orderNo
     * @return
     */
    public List<ProductStockFlowingRes> getSendMsg(String orderNo) {
        List<ProductStockFlowingDo> flowingDoList = productStockFlowingDao.selectList(new LambdaQueryWrapper<ProductStockFlowingDo>().eq(ProductStockFlowingDo::getNoteNo, orderNo).and(i -> i.eq(ProductStockFlowingDo::getType, StaticDict.Product_Flowing_Type.Output.getValue()).or().eq(ProductStockFlowingDo::getType, StaticDict.Product_Flowing_Type.ReleaseLock.getValue())).orderByDesc(ProductStockFlowingDo::getId));
        List<ProductStockFlowingRes> resList = productStockFlowingService.getResList(flowingDoList);
        return resList;
    }

    //查询明细之后要执行的业务定制处理
    private OrderOutputDetailRes handlerDetailAfter(OrderOutputDo entityDo, OrderOutputDetailRes res) {
        if (shopDao.selectById(entityDo.getShopId()) != null) {
            res.setShop(shopDao.selectById(entityDo.getShopId()).getShopName());
        }
        if (storageDao.selectById(entityDo.getStorageId()) != null) {
            res.setStorage(storageDao.selectById(entityDo.getStorageId()).getStorageName());
        }
        if (dicBusinessItemDao.selectById(entityDo.getTrackId()) != null) {
            res.setTrackName(dicBusinessItemDao.selectById(entityDo.getTrackId()).getDicItemValue());
        }
        res.setReceiverName(entityDo.getReceiverName());
        res.setOrderNumber(entityDo.getOrderOutputNumber());
        if (entityDo.getDeliveryDate() != null) res.setDeliveryDate(TimeUtils.formatDate(entityDo.getDeliveryDate()));
//        res.setOrderTypeName(entityDo.getOrderType() != null && entityDo.getOrderType() == 2 ? ORDER_OUTPUT_TYPE_2 : ORDER_OUTPUT_TYPE_1);
        res.setShipmentTypeName(StringsUtil.createI18Message(entityDo.getShipmentType() != null && entityDo.getShipmentType() == 1 ? SHIPMENT_TYPE_1 : SHIPMENT_TYPE_0));
        //查询对应包裹列表
        //package
        List<OrderOutputPackageDo> packageDoList = packageDao.selectList(new LambdaQueryWrapper<OrderOutputPackageDo>().eq(OrderOutputPackageDo::getOrderOutputId, res.getId()));
        List<OrderOutputPackageDetail> packageResList = new ArrayList<>();
        //product
        List<OrderOutputProductDo> allProductDoList = productDao.selectList(new LambdaQueryWrapper<OrderOutputProductDo>().eq(OrderOutputProductDo::getOrderId, entityDo.getId()));
        //product根据 packageId分类
        Map<Long, List<OrderOutputProductDo>> productMapList = allProductDoList.stream().collect(Collectors.groupingBy(OrderOutputProductDo::getPackageId));
        //统计订单的所有productId
        List<Long> productIds = allProductDoList.stream().map(OrderOutputProductDo::getProductId).collect(Collectors.toList());
        //库存
        Map<String, String> param = new HashMap<>();
        param.put("storageId", entityDo.getStorageId() + "");
        param.put("shopId", entityDo.getShopId() + "");
        if (productIds.size() > 0) {
            param.put("productIds", StringUtils.join(productIds, ","));
        }
        List<StockRecordPageRes> stockList = stockRecordService.getList(param);
        Map<Long, List<StockRecordPageRes>> stockListMap = stockList.stream().collect(Collectors.groupingBy(StockRecordPageRes::getProductInfoId));

        for (OrderOutputPackageDo packageDo : packageDoList) {
            OrderOutputPackageDetail packageDetailRes = new OrderOutputPackageDetail();
            BeanUtils.copyProperties(packageDo, packageDetailRes);
            packageDetailRes.setCount(packageDo.getCount());
            packageDetailRes.setSize(packageDo.getLength() + "+" + packageDo.getWidth() + "+" + packageDo.getHeight());
            //product
            List<OrderOutputProductDetail> productResList = new ArrayList<>();
//            List<OrderOutputProductDo> productDoList = productDao.selectList(new LambdaQueryWrapper<OrderOutputProductDo>()
//                    .eq(OrderOutputProductDo::getPackageId, packageDo.getId()));
            List<OrderOutputProductDo> productDoList = productMapList.get(packageDo.getId());
            for (OrderOutputProductDo productDetail : productDoList) {
                OrderOutputProductDetail productDetailRes = new OrderOutputProductDetail();
                BeanUtils.copyProperties(productDetail, productDetailRes);
                ProductInfoDo productInfoDo = productInfoDao.selectById(productDetail.getProductId());
                if (productInfoDo != null) {
                    productDetailRes.setCommoditySku(productInfoDo.getCommoditySku());
                    productDetailRes.setStorageSku(productInfoDo.getStorageSku());
                    productDetailRes.setCommodityName(productInfoDo.getCommodityName());
                    if (stockListMap.get(productInfoDo.getId()) != null) {
                        productDetailRes.setCanSellCount(stockListMap.get(productInfoDo.getId()).get(0).getCanSellCount());
                    }
                }

                productResList.add(productDetailRes);
            }
            packageDetailRes.setProductList(productResList);
            packageResList.add(packageDetailRes);
        }

        res.setPackageList(packageResList);
        //package
        List<OrderOutputPackageDetailDo> packageDetailDoList = packageDetailDao.selectList(new LambdaQueryWrapper<OrderOutputPackageDetailDo>().eq(OrderOutputPackageDetailDo::getOrderOutputId, res.getId()));
        List<OrderOutputPackageDetail> packageDetailResList = new ArrayList<>();
        if (packageDetailDoList != null && packageDetailDoList.size() > 0) {
            packageDetailResList = packageDetailDoList.stream().map(new Function<OrderOutputPackageDetailDo, OrderOutputPackageDetail>() {
                @Override
                public OrderOutputPackageDetail apply(OrderOutputPackageDetailDo orderOutputPackageDetailDo) {
                    OrderOutputPackageDetail detail = new OrderOutputPackageDetail();
                    List<OrderOutputProductDetail> productResList = new ArrayList<>();
                    BeanUtils.copyProperties(orderOutputPackageDetailDo, detail);
                    if (StringUtils.isNotBlank(orderOutputPackageDetailDo.getInSkuId())) {
                        String[] split = orderOutputPackageDetailDo.getInSkuId().split(",");
                        Map<String, Long> stringLongMap = Arrays.asList(split).stream().collect(Collectors.groupingBy(s -> s, Collectors.counting()));
                        for (String productId : stringLongMap.keySet()) {
                            OrderOutputProductDetail productDetailRes = new OrderOutputProductDetail();
                            if (StringUtils.isNotBlank(productId)) {
                                if (StringUtils.isBlank(productId)) continue;
                                ProductInfoDo productInfoDo = productInfoDao.selectById(productId);
                                if (productInfoDo != null) {
                                    if (stringLongMap.get(productId) == null) {
                                        continue;
                                    } else {
                                        productDetailRes.setCount(stringLongMap.get(productId).intValue());
                                    }
                                    if (stringLongMap.get(productId) == null) {
                                        continue;
                                    } else {
                                        productDetailRes.setCount(stringLongMap.get(productId).intValue());
                                    }
                                    productDetailRes.setCommoditySku(productInfoDo.getCommoditySku());
                                    productDetailRes.setStorageSku(productInfoDo.getStorageSku());
                                    productDetailRes.setCommodityName(productInfoDo.getCommodityName());
//                                    if (stockListMap.get(productInfoDo.getId()) != null) {
//                                        productDetailRes.setCanSellCount(stockListMap.get(productInfoDo.getId()).get(0).getCanSellCount());
//                                    }
                                    productResList.add(productDetailRes);
                                }
                            }
                        }
                        detail.setProductList(productResList);
                    }
                    return detail;
                }
            }).collect(Collectors.toList());
        }
        res.setPackageDetailList(packageDetailResList);


        //查询日志
        List<OperateRes> operateResList = operateRecordDao.getOperateList(entityDo.getId(), 3);
        res.setOperateResList(operateResList);
        return res;
    }

    @Override
    public SingleResult pageInit(Long companyId, Long userId) {
        Map map = new HashMap();
        map.put("storageList", storageService.getList(new HashMap<>()));
        List<Long> ids = new ArrayList<>();
        map.put("trackList", dicBusinessItemService.getDicItemList(DicBusinessConstant.trackCompany, true));
        List<Map> shopList = companyService.getInitList(companyId);
        map.put("shopList", shopList);
        List<ProductInfoDo> productInfoDos = productInfoDao.selectList(null);
        List<Map> mapList = new ArrayList<>();

        for (ProductInfoDo productInfoDo : productInfoDos) {
            Map<String, Object> productMap = new HashMap<>();
            productMap.put("id", productInfoDo.getId());
            productMap.put("value", productInfoDo.getCommoditySku());
            mapList.add(productMap);
        }
        map.put("sku", mapList);
        //公司相关信息
        List<CompanyDo> companyDos = mCompanyDao.selectList(null);
        List<Map> companyList = new ArrayList<>();
        for (CompanyDo companyDo : companyDos) {
            Map<String, Object> companyMap = new HashMap<>();
            companyMap.put("id", companyDo.getId());
            companyMap.put("value", companyDo.getName());
            companyList.add(companyMap);
        }
        map.put("company", companyList);
        return SingleResult.success(map);
    }

    @Override
    public List<Map> uploadExcelInit(Long userid) {
        Map map = new HashMap();
        map.put("storageList", storageService.getList(new HashMap<>()));
        List<Map> shopList = new ArrayList<>();
        List<ShopDo> shopDoList = shopService.list();
        if (!CollectionUtils.isEmpty(shopDoList)) {
            for (ShopDo storageDo : shopDoList) {
                Map storageMap = new HashMap();
                storageMap.put("id", storageDo.getId());
                storageMap.put("value", storageDo.getShopName());
                shopList.add(storageMap);
            }
        }
        Map map1 = new HashMap();
        map1.put("shopList", shopList);
        List<Map> list = new ArrayList<>();
        list.add(map);
        list.add(map1);
        return list;
    }

    @Override
    public List<OrderOutputListRes> getList(Map<String, String> map) {
        QueryWrapper<OrderOutputDo> wrapper = queryBuild(map);
        List<OrderOutputDo> list = this.list(wrapper);
        List<OrderOutputListRes> result = handlerListAfter(list);
        return result;
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<OrderOutputDo> wrapper = queryBuild(map);
        IPage<OrderOutputDo> page = pageInit(map);
        List<OrderOutputDo> orderOutputDoList = this.dao.listPage(page, map);
        List<OrderOutputListRes> resList = handlerListAfter(orderOutputDoList);
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        result.setMapInfo(countStatus(map));
        return result;
    }

    private Map countStatus(Map<String, String> map) {
        List<Map> result = new ArrayList<>();
        Map mapTotal = new HashMap();
        map.put("status", "");
        List<OrderOutputDo> list = dao.listPage(map);
        mapTotal.put("count", list.size());
        mapTotal.put("id", "");
        mapTotal.put("name", StringsUtil.createI18Message("全部"));
        result.add(mapTotal);

        Map<Long, List<OrderOutputDo>> listMap = list.stream().collect(Collectors.groupingBy(OrderOutputDo::getStatus));
        LambdaQueryWrapper<DicBusinessItemDo> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.outPutStatus);
        wrapper1.orderByAsc(DicBusinessItemDo::getSort);

        List<DicBusinessItemDo> itemDoList = dicBusinessItemDao.selectList(wrapper1);
        for (DicBusinessItemDo itemDo : itemDoList) {
            Map map1 = new HashMap();
            map.put("status", itemDo.getId() + "");
            map1.put("id", itemDo.getId());
            if (listMap.get(itemDo.getId()) != null) {
                map1.put("count", listMap.get(itemDo.getId()).size());
            } else {
                map1.put("count", 0);
            }
            map1.put("name", StringsUtil.createI18Message(itemDo.getDicItemValue()));
            result.add(map1);
        }

        Map map2 = new HashMap();
        map2.put("census", result);
        return map2;
    }

    //查询分页列表之后对列表数据的处理
    private List<OrderOutputListRes> handlerListAfter(List<OrderOutputDo> list) {
        List<OrderOutputListRes> result = new ArrayList<>();
        for (OrderOutputDo orderOutputDo : list) {
            OrderOutputListRes listRes = new OrderOutputListRes();
            BeanUtils.copyProperties(orderOutputDo, listRes);
            StorageDo storageDo = storageDao.selectById(orderOutputDo.getStorageId());
            if (storageDo != null) {
                listRes.setStorageName(storageDo.getStorageName());
            }

            DicBusinessItemDo dic = dicBusinessItemDao.selectById(orderOutputDo.getTrackId());
            if (dic != null) {
                listRes.setTrackName(dic.getDicItemValue());
            }

            DicBusinessItemDo dicBusinessItemDo = dicBusinessItemDao.selectById(orderOutputDo.getStatus());
            if (dicBusinessItemDo != null) {
                listRes.setStatus(dicBusinessItemDo.getDicItemValue());
            }
            if (1 == orderOutputDo.getShipmentType()) {
                listRes.setShipmentTypeName("SHIPMENT_TYPE_1");
            } else {
                listRes.setShipmentTypeName("SHIPMENT_TYPE_0");
            }
            CompanyDo companyDo = mCompanyDao.selectById(orderOutputDo.getCompanyId());
            if (companyDo != null) {
                listRes.setCompanyCode(companyDo.getCompanyCode());
            }

            listRes.setNumber(orderOutputDo.getOrderOutputNumber());
            listRes.setSendDate(TimeUtils.formatDate(orderOutputDo.getSendDate()));
            listRes.setPoNumber(orderOutputDo.getPoNumber());
            listRes.setVolume(getProductVolume(orderOutputDo) + "");
            listRes.setReceiverName(orderOutputDo.getReceiverName());

            if (orderOutputDo.getDeliveryDate() != null)
                listRes.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate()));

            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("order_output_id", orderOutputDo.getId());
            List<OrderOutputPackageDo> packageDoList = packageDao.selectList(wrapper);
            if (packageDoList == null) continue;
            if (packageDoList.size() > 1) {

            } else if (packageDoList.size() == 1) {
                OrderOutputPackageDo packageDo = packageDoList.get(0);
                Double size = packageDo.getLength() + packageDo.getWidth() + packageDo.getHeight();
                listRes.setShipPrice(new BigDecimal(size).setScale(0, RoundingMode.UP).doubleValue());
            }
            if (StringUtils.isBlank(listRes.getCommoditySku())) {
                QueryWrapper wrapper1 = new QueryWrapper();
                wrapper1.eq("order_id", orderOutputDo.getId());
                List<OrderOutputProductDo> productList = productDao.selectList(wrapper1);
                StringBuilder sb = new StringBuilder();
                for (OrderOutputProductDo productDo : productList) {
                    if (sb.length() > 0) {
                        sb.append(",");
                    }
                    ProductInfoDo productInfoDo = productInfoDao.selectById(productDo.getProductId());
                    if (productInfoDo != null) sb.append(productInfoDo.getCommoditySku());
                }
                listRes.setCommoditySku(sb.toString());
            }
            result.add(listRes);
        }
        return result;
    }

    private double getProductVolume(OrderOutputDo orderOutputDo) {
        double volume = 0;
        LambdaQueryWrapper<OrderOutputProductDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderOutputProductDo::getOrderId, orderOutputDo.getId());
        List<OrderOutputProductDo> orderOutputProductDoList = productDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(orderOutputProductDoList)) {
            for (OrderOutputProductDo productDo : orderOutputProductDoList) {
                ProductInfoDo productInfoDo = productInfoDao.selectById(productDo.getProductId());
                if (productInfoDo != null) {
                    volume += (productInfoDo.getHeight() * productInfoDo.getWidth() * productInfoDo.getLength());
                }
            }
        }
        return volume / 1000000;

    }

    private IPage<OrderOutputDo> pageInit(Map<String, String> map) {
        IPage<OrderOutputDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<OrderOutputDo> queryBuild(Map<String, String> map) {
        QueryWrapper<OrderOutputDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            String keyword = map.get("keyword").replaceAll(" ", "%").replaceAll("　", "%").replaceAll("-", "%");
            wrapper.or(orderOutputDoQueryWrapper -> orderOutputDoQueryWrapper.like("order_no", map.get("keyword")).or(true).like("order_output_number", map.get("keyword")).or(true).like("tel_phone", keyword).or(true).like("track_number", keyword).or(true).like("receiver_name", keyword));
        }
        if (StringUtils.isNotBlank(map.get("status"))) {
            wrapper.eq("status", map.get("status"));
        }
        if (StringUtils.isNotBlank(map.get("checkType"))) {
            wrapper.eq("check_type", map.get("checkType"));
        }
        if (StringUtils.isNotBlank(map.get("fbaStorageId"))) {
            wrapper.eq("fba_storage_id", map.get("fbaStorageId"));
        }
        if (StringUtils.isNotBlank(map.get("startDate"))) {
            wrapper.ge("send_date", map.get("startDate"));
        }
        if (StringUtils.isNotBlank(map.get("endDate"))) {
            wrapper.le("send_date", map.get("endDate"));
        }
        if (StringUtils.isNotBlank(map.get("storageId"))) {
            wrapper.eq("storage_id", map.get("storageId"));
        }
        if (StringUtils.isNotBlank(map.get("trackId"))) {
            wrapper.eq("track_id", map.get("trackId"));
        }
        if (StringUtils.isNotBlank(map.get("shopId"))) {
            wrapper.eq("shop_id", map.get("shopId"));
        }
//        if (StringUtils.isNotBlank(map.get("orderType"))) {
//            wrapper.eq("order_type", map.get("orderType"));
//        }
        if (StringUtils.isNotBlank(map.get("companyId"))) {
            wrapper.eq("company_id", map.get("companyId"));
        }
        wrapper.orderByDesc("id");
        return wrapper;
    }

    @Override
    public Map dealwithTrackNumberExcel(MultipartFile file, Integer storageId, Long userid) {
        List<OrderOutputTrackNumberExcelImport> excelImportList = new ArrayList<>();
        if (StringUtils.isEmpty(file.getName())) {
            throw new BizException(SysConstant.File_Name_Null);
        }
        if (storageId == null || storageId == 0) {
            throw new BizException(SysConstant.Pls_Choose_Send_Storage);
        }
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!GlobalConstants.IMG_TYPE_XLS.equals(suffix.toUpperCase()) && !GlobalConstants.IMG_TYPE_XLSX.equals(suffix.toUpperCase())) {
            throw new BizException(SysConstant.File_Form_Incorrect);
        }
        try {
            excelImportList = ExcelUtils.importExcel(file, 0, 0, OrderOutputTrackNumberExcelImport.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BizException(e.getMessage());
        }
        if (excelImportList == null) {
            throw new BizException(SysConstant.File_FormWork_Incorrect);
        }

        threadPoolTaskExecutor.execute(() -> {
            //将文件保存到服务器
            try {

                //方案一：先上传到临时文件夹，再上传到正式文件夹
//            Long fileId = fileService.uploadTempFile(fileName, mpart.getInputStream(), null);
//            addFileMoreDo(fileId, mailId);
//            fileService.uploadFile(fileId);
                //方案二 直接上传到正式路径
                Long fileId = fileService.uploadFileToFormalPath(file.getInputStream(), file.getOriginalFilename());
                if (fileId != null && fileId != 0L) {
                    fileService.addFileMoreDo(fileId, 0L, "orderOutput");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return dealwithExcelData(excelImportList, storageId, userid);
    }

    @Override
    public List<String> dealwithExcel(MultipartFile file, int storageId, int shopId, Long userid) {
        List<OrderOutputExcelImport> excelImportList = new ArrayList<>();
        if (StringUtils.isEmpty(file.getName())) {
            throw new BizException(SysConstant.File_Name_Null);
        }
        if (storageId == 0) {
            throw new BizException(SysConstant.Pls_Choose_Send_Storage);
        }
        if (shopId == 0) {
            throw new BizException(SysConstant.Pls_Choose_Shop);
        }
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!GlobalConstants.IMG_TYPE_XLS.equals(suffix.toUpperCase()) && !GlobalConstants.IMG_TYPE_XLSX.equals(suffix.toUpperCase())) {
            throw new BizException(SysConstant.File_Form_Incorrect);
        }
        try {
            excelImportList = ExcelUtils.importExcel(file, 0, 1, OrderOutputExcelImport.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (excelImportList == null || excelImportList.size() == 0) {
            throw new BizException(SysConstant.File_FormWork_Incorrect);
        }
        for (OrderOutputExcelImport excelImport : excelImportList) {
            if (StringUtils.isBlank(excelImport.getPostCode())) continue;
            dealwithExcelData(excelImport, shopId, storageId, userid);
        }
        return null;
    }

    private OrderOutputDo dealwithExcelData(OrderOutputExcelImport excelData, int shopId, int storageId, Long userid) {
        OrderOutputDo outputDo = new OrderOutputDo();
        outputDo.setSendDate(new Date());
        outputDo.setStatus(DicBusinessItemConstant.outCreateState);
        ShopDo shopDo = shopDao.selectById(shopId);
        if (shopDo == null) {
            throw new BizException(SysConstant.Shop_NotExist);
        }
        outputDo.setShopId((long) shopId);
        outputDo.setCompanyId(shopDo.getCompanyId());
        outputDo.setStorageId((long) storageId);
//        outputDo.setOrderType(1);
        if (StringUtils.isNotBlank(excelData.getOrderNo()))
            outputDo.setOrderNo(excelData.getOrderNo().replaceAll("\\n", "").replaceAll("\\\"", "").replaceAll(",", ""));
        outputDo.setCreateBy(userid);
        outputDo.setCreateTime(new Date());
        if (StringUtils.isNotBlank(excelData.getPostCode()))
            outputDo.setPostCode(excelData.getPostCode().trim().replaceAll("\\n", "").replaceAll("\\\"", "").replaceAll(",", ""));
        if (StringUtils.isNotBlank(excelData.getTelPhone()))
            outputDo.setTelPhone(excelData.getTelPhone().trim().replaceAll("\\n", "").replaceAll("\\\"", "").replaceAll(",", ""));
        if (StringUtils.isNotBlank(excelData.getArea()))
            outputDo.setArea(excelData.getArea().trim().replaceAll("\\n", "").replaceAll("\\\"", "").replaceAll(",", ""));
        if (StringUtils.isNotBlank(excelData.getAddress()))
            outputDo.setAddress(excelData.getAddress().trim().replaceAll("\\n", "").replaceAll("\\\"", "").replaceAll(",", ""));
        if (StringUtils.isNotBlank(excelData.getReceiverName()))
            outputDo.setReceiverName(excelData.getReceiverName().trim().replaceAll("\\n", "").replaceAll("\\\"", "").replaceAll(",", ""));
        if (StringUtils.isNotBlank(excelData.getDeliveryDate()))
            outputDo.setDeliveryDate(TimeUtils.parseDate(excelData.getDeliveryDate()));
        outputDo.setDeliveryTime(excelData.getDeliveryTime());
        if (StringUtils.isNotBlank(excelData.getTips()))
            outputDo.setTips(excelData.getTips().trim().replaceAll("\\n", "").replaceAll(",", ""));
        outputDo.setCod(excelData.getCod());
        if (SHIPMENT_TYPE_1.equals(excelData.getShipmentType())) {
            outputDo.setShipmentType(1);
        } else {
            outputDo.setShipmentType(0);
        }
//        outputDo.setTrackId(8l);
        save(outputDo);
        operateRecordDao.operateAddRecord(SysConstant.OPERATE_CREATE_ORDER, outputDo.getId(), userid, 3);
//        operateRecord("创建", outputDo.getId(), userid);
        dealwithExcelProduct(outputDo, excelData, shopDo.getCompanyId());
        return null;
    }

    private void dealwithExcelProduct(OrderOutputDo outputDo, OrderOutputExcelImport excelData, Long companyId) {
        OrderOutputPackageDo packageDo = new OrderOutputPackageDo();
        packageDo.setOrderOutputId(outputDo.getId());
        packageDo.setCreateBy(outputDo.getCreateBy());
        packageDo.setCreateTime(new Date());
        packageDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        packageDao.insert(packageDo);
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder stringBuilder2 = new StringBuilder();
        //todo 产品数量过多时需要人工审核，状态改为-1
        if (StringUtils.isNotBlank(excelData.getCommoditySku1())) {
            ProductInfoDo productInfoDo1 = productInfoDao.selectById(getProductId(excelData.getCommoditySku1(), companyId));
            if (productInfoDo1 == null) {
                throw new BizException(SysConstant.Product_NotExist_Sku, excelData.getCommoditySku1());
            }
            OrderOutputProductDo outputProductDo1 = new OrderOutputProductDo();
            outputProductDo1.setProductId(productInfoDo1.getId());
            outputProductDo1.setOrderId(outputDo.getId());
            outputProductDo1.setCount(excelData.getCount1());
//        outputProductDo1.setCommoditySku(productInfoDo.getCommoditySku());
//        outputProductDo1.setStorageSku(productInfoDo.getStorageSku());
            outputProductDo1.setPackageId(packageDo.getId());
            outputProductDo1.setCreateBy(outputDo.getCreateBy());
            outputProductDo1.setCreateTime(new Date());
            outputProductDo1.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);

            ProductInfoDo productInfoDo = productInfoDao.selectById(outputProductDo1.getProductId());
            if (productInfoDo == null) {
                throw new BizException(SysConstant.Product_NotExist);
            }
            String productSku = productInfoDo.getCommoditySku();

            verifyStock(outputDo.getShopId(), outputDo.getStorageId(), outputProductDo1.getProductId(), outputProductDo1.getCount(), productSku);
            productDao.insert(outputProductDo1);
            stringBuilder.append(productSku);
            stringBuilder2.append(productInfoDo.getStorageSku());
        } else {
            throw new BizException(SysConstant.Product_NotExist_Sku, excelData.getCommoditySku1());
        }
        //产品2
        if (StringUtils.isNotBlank(excelData.getCommoditySku2())) {
            ProductInfoDo productInfoDo2 = productInfoDao.selectById(getProductId(excelData.getCommoditySku2(), companyId));
            if (productInfoDo2 == null) {
                throw new BizException(SysConstant.Product_NotExist_Sku, excelData.getCommoditySku2());
            }
            OrderOutputProductDo outputProductDo2 = new OrderOutputProductDo();
            outputProductDo2.setProductId(productInfoDo2.getId());
            outputProductDo2.setOrderId(outputDo.getId());
            outputProductDo2.setCount(excelData.getCount2());
//        outputProductDo2.setCommoditySku(productInfoDo.getCommoditySku());
//        outputProductDo2.setStorageSku(productInfoDo.getStorageSku());
            outputProductDo2.setPackageId(packageDo.getId());
            outputProductDo2.setCreateBy(outputDo.getCreateBy());
            outputProductDo2.setCreateTime(new Date());
            outputProductDo2.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
            String productSku = "";
            ProductInfoDo productInfoDo = productInfoDao.selectById(outputProductDo2.getProductId());
            if (productInfoDo != null) {
                productSku = productInfoDo.getCommoditySku();
            }
            verifyStock(outputDo.getShopId(), outputDo.getStorageId(), outputProductDo2.getProductId(), outputProductDo2.getCount(), productSku);
            productDao.insert(outputProductDo2);
            if (stringBuilder.length() > 0) stringBuilder.append(",");
            stringBuilder.append(productSku);
            if (stringBuilder2.length() > 0) stringBuilder2.append(",");
            stringBuilder2.append(productInfoDo.getStorageSku());
        }
        //产品3
        if (StringUtils.isNotBlank(excelData.getCommoditySku3())) {
            ProductInfoDo productInfoDo3 = productInfoDao.selectById(getProductId(excelData.getCommoditySku3(), companyId));
            if (productInfoDo3 == null) {
                throw new BizException(SysConstant.Product_NotExist_Sku, excelData.getCommoditySku3());
            }
            OrderOutputProductDo outputProductDo3 = new OrderOutputProductDo();
            outputProductDo3.setProductId(productInfoDo3.getId());
            outputProductDo3.setOrderId(outputDo.getId());
            outputProductDo3.setCount(excelData.getCount3());
//        outputProductDo3.setCommoditySku(productInfoDo.getCommoditySku());
//        outputProductDo3.setStorageSku(productInfoDo.getStorageSku());
            outputProductDo3.setPackageId(packageDo.getId());
            outputProductDo3.setCreateBy(outputDo.getCreateBy());
            outputProductDo3.setCreateTime(new Date());
            outputProductDo3.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
            String productSku = "";
            ProductInfoDo productInfoDo = productInfoDao.selectById(outputProductDo3.getProductId());
            if (productInfoDo != null) {
                productSku = productInfoDo.getCommoditySku();
            }
            verifyStock(outputDo.getShopId(), outputDo.getStorageId(), outputProductDo3.getProductId(), outputProductDo3.getCount(), productSku);
            productDao.insert(outputProductDo3);
            if (stringBuilder.length() > 0) stringBuilder.append(",");
            stringBuilder.append(productSku);
            if (stringBuilder2.length() > 0) stringBuilder2.append(",");
            stringBuilder2.append(productInfoDo.getStorageSku());
        }
        //产品4
        if (StringUtils.isNotBlank(excelData.getCommoditySku4())) {
            ProductInfoDo productInfoDo4 = productInfoDao.selectById(getProductId(excelData.getCommoditySku4(), companyId));
            if (productInfoDo4 == null) {
                throw new BizException(SysConstant.Product_NotExist_Sku, excelData.getCommoditySku4());
            }
            OrderOutputProductDo outputProductDo4 = new OrderOutputProductDo();
            outputProductDo4.setProductId(productInfoDo4.getId());
            outputProductDo4.setCount(excelData.getCount4());
            outputProductDo4.setOrderId(outputDo.getId());

//        outputProductDo4.setCommoditySku(productInfoDo.getCommoditySku());
//        outputProductDo4.setStorageSku(productInfoDo.getStorageSku());
            outputProductDo4.setPackageId(packageDo.getId());
            outputProductDo4.setCreateBy(outputDo.getCreateBy());
            outputProductDo4.setCreateTime(new Date());
            outputProductDo4.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
            ProductInfoDo productInfoDo = productInfoDao.selectById(outputProductDo4.getProductId());
            String productSku = "";
            if (productInfoDo != null) {
                productSku = productInfoDo.getCommoditySku();
            }
            verifyStock(outputDo.getShopId(), outputDo.getStorageId(), outputProductDo4.getProductId(), outputProductDo4.getCount(), productSku);
            productDao.insert(outputProductDo4);
            if (stringBuilder.length() > 0) stringBuilder.append(",");
            stringBuilder.append(productSku);
            if (stringBuilder2.length() > 0) stringBuilder2.append(",");
            stringBuilder2.append(productInfoDo.getStorageSku());
        }
        outputDo.setOrderOutputNumber(OrderCodeUtil.getOrderOutNumber(outputDo.getId()));
        outputDo.setStorageSku(stringBuilder2.toString());
        outputDo.setCommoditySku(stringBuilder.toString());
        updateTrackId(outputDo);
    }

    @Override
    public void exportExcel(Map<String, String> map, List<Long> ids, HttpServletResponse response) throws IOException {
//        QueryWrapper<OrderOutputDo> wrapper = queryBuild(map);
        List<OrderOutputDo> orderOutputDoList;
        if (ids != null && ids.size() > 0) {
            orderOutputDoList = this.baseMapper.selectBatchIds(ids);
        } else {
            orderOutputDoList = this.baseMapper.selectList1(map);
        }
        if (orderOutputDoList.size() > 10000) {
//            response.setStatus();
            response.sendError(500, "数据超过10000条，请分日期导出");
            throw new BizException();
        }
        List<OrderOutputExcelExportVo> excelExportVoList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(orderOutputDoList)) {
            for (OrderOutputDo orderOutputDo : orderOutputDoList) {
                OrderOutputExcelExportVo excelExportVo = new OrderOutputExcelExportVo();

                BeanUtils.copyProperties(orderOutputDo, excelExportVo);

                DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(orderOutputDo.getStatus());
                if (businessItemDo != null) {
                    excelExportVo.setStatus(businessItemDo.getDicItemValue());
                }
                ShopDo shopDo = shopDao.selectById(orderOutputDo.getShopId());
                if (shopDo != null) {
                    excelExportVo.setShopName(shopDo.getShopName());
                }
                StorageDo storageDo = storageDao.selectById(orderOutputDo.getStorageId());
                if (storageDo != null) {
                    excelExportVo.setStorageName(storageDo.getStorageName());
//                    excelExportVo.setStorageSku(storageDo.getCode());
                }
                CompanyDo companyDo = companyDao.selectById(orderOutputDo.getCompanyId());
                if (companyDo != null) {
                    excelExportVo.setCompanyName(companyDo.getCompanyCode());
                }
                DicBusinessItemDo track = dicBusinessItemDao.selectById(orderOutputDo.getTrackId());
                if (track != null) {
                    excelExportVo.setTrackName(track.getDicItemValue());
                }
                int count = productDao.selectCountByOrderId(orderOutputDo.getId());
                excelExportVo.setSkuCount(count);
//                LambdaQueryWrapper<OrderOutputProductDo> productDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
//                productDoLambdaQueryWrapper.eq(OrderOutputProductDo::getOrderId, orderOutputDo.getId());
//                List<OrderOutputProductDo> productDoList = productDao.selectList(productDoLambdaQueryWrapper);
//                int count = 0;
//                if (!CollectionUtils.isEmpty(productDoList)) {
//                    count = productDoList.stream().mapToInt(OrderOutputProductDo::getCount).sum();
//                }
//                excelExportVo.setSkuCount(count);
                //package
//                if (StringUtils.isBlank(excelExportVo.getCommoditySku())) {
                LambdaQueryWrapper<OrderOutputPackageDo> packageDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                packageDoLambdaQueryWrapper.eq(OrderOutputPackageDo::getOrderOutputId, orderOutputDo.getId());
                List<OrderOutputPackageDo> packageDoList = packageDao.selectList(packageDoLambdaQueryWrapper);
                if (!CollectionUtils.isEmpty(packageDoList)) {
                    List<OrderOutputPackageExcelExportVo> packageExcelExportVoList = new ArrayList<>();
                    for (OrderOutputPackageDo packageDo : packageDoList) {
                        StringBuilder stringBuilder = new StringBuilder();
                        StringBuilder stringBuilder1 = new StringBuilder();
                        OrderOutputPackageExcelExportVo packageExcelExportVo = new OrderOutputPackageExcelExportVo();
                        BeanUtils.copyProperties(packageDo, packageExcelExportVo);
                        LambdaQueryWrapper<OrderOutputProductDo> productDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        productDoLambdaQueryWrapper.eq(OrderOutputProductDo::getPackageId, packageDo.getId());
                        List<OrderOutputProductDo> productDoList = productDao.selectList(productDoLambdaQueryWrapper);
                        if (!CollectionUtils.isEmpty(productDoList)) {
                            List<OrderOutputProductExcelExportVo> productExcelExportVoList = new ArrayList<>();
                            for (OrderOutputProductDo productDo : productDoList) {
                                OrderOutputProductExcelExportVo productExcelExportVo = new OrderOutputProductExcelExportVo();
                                BeanUtils.copyProperties(productDo, productExcelExportVo);
                                ProductInfoDo productInfoDo = productInfoDao.selectById(productDo.getProductId());
                                if (productInfoDo != null) {
                                    if (stringBuilder.length() > 1) stringBuilder.append(",");
                                    stringBuilder.append(productInfoDo.getCommoditySku());
                                    if (stringBuilder1.length() > 1) stringBuilder1.append(",");
                                    stringBuilder1.append(productInfoDo.getStorageSku());
                                    productExcelExportVo.setCommoditySku(productInfoDo.getCommoditySku());
                                    productExcelExportVo.setStorageSku(productInfoDo.getStorageSku());
                                }
                                productExcelExportVo.setCount(productDo.getCount());
                                productExcelExportVoList.add(productExcelExportVo);
                            }
                            packageExcelExportVo.setProductExcelExportVoList(productExcelExportVoList);
                        }


                        packageExcelExportVoList.add(packageExcelExportVo);
                        excelExportVo.setCommoditySku(stringBuilder.toString());
                        excelExportVo.setStorageSku(stringBuilder1.toString());
                        excelExportVo.setPackageExcelExportVoList(packageExcelExportVoList);
                    }
                }
//                }

                excelExportVoList.add(excelExportVo);
            }
        }

        ExcelUtils.exportExcel(excelExportVoList, OrderOutputExcelExportVo.class, "出库订单", new ExportParams(), response);
    }

    @Override
    public List<String> addRakutenList(List<OrderOutputAddReq> orderOutputAddReqList, Long currentUserId) {
        List<String> failedOrderids = new ArrayList<>();
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            String value = null;
            try {
                value = add(outputAddReq, currentUserId);
            } catch (BizException e) {
                e.printStackTrace();
                value = StringsUtil.createI18Message(e.getMessage(), e.getArgs());
            }
            if (value != null) {
                failedOrderids.add(value);
            } else {
                rakutenDao.updateOrderSendOut(outputAddReq.getOrderNo());
            }
        }
        return failedOrderids;
    }

    @Override
    public List<String> addAmazonList(Iterable<OrderOutputAddReq> orderOutputAddReqList, Long userId) {
        List<String> failedOrderids = new ArrayList<>();
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            String value = null;
            try {
                value = add(outputAddReq, userId);
            } catch (BizException e) {
                e.printStackTrace();
                value = e.getMessage();
            }
            if (value != null) {
                failedOrderids.add(value);
            } else {
                amazonDao.updateOrderSendOut(outputAddReq.getOrderNo());
            }
        }
        return failedOrderids;
    }


    @Override
    public List<String> addShopifyList(Iterable<OrderOutputAddReq> orderOutputAddReqList, Long userId) {
        List<String> failedOrderids = new ArrayList<>();
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            String value = null;
            try {
                value = add(outputAddReq, userId);
            } catch (BizException e) {
                e.printStackTrace();
                value = e.getMessage();
            }
            if (value != null) {
                failedOrderids.add(value);
            } else {
                shopifyDao.updateOrderSendOut(outputAddReq.getOrderNo().replaceAll(SHOPIFY_PREFIX, ""));
            }
        }
        return failedOrderids;
    }

    @Override
    public void uploadTrackNumberData(List<String> excelImportList, int storageId, Long userid) {
        List<String> orderNumbers = new ArrayList<>();
        for (int i = 0; i < excelImportList.size(); i++) {
            LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper();
            wrapper.eq(OrderOutputDo::getOrderOutputNumber, excelImportList.get(i));
            OrderOutputDo outputDo = dao.selectOne(wrapper);
            if (outputDo != null && StringUtils.isNotBlank(outputDo.getTrackNumber())) {
                orderNumbers.add(outputDo.getOrderOutputNumber());
            }
        }
        if (orderNumbers.size() > 0) autoUploadExpressNumber(orderNumbers);
//        executeTaskT(excelImportList);Amz
    }

    @Override
    public Map dealwithExcelData(List<OrderOutputTrackNumberExcelImport> excelImportList, int storageId, final Long userid) {
        Map map = new HashMap();
        int totalCount = 0;
        List<String> orderNumbers = new ArrayList<>();
        Map<Long, String> orderListSuccess = new HashMap<>();
        Map<String, Integer> mapDuplicate = new HashMap<>();
        Map<String, List<OrderOutputTrackNumberExcelImport>> mapCollect = excelImportList.stream().filter(excelData -> excelData != null && excelData.getOrderOTNumber() != null).map(orderOutputTrackNumberExcelImport -> {
            if (orderOutputTrackNumberExcelImport.getOrderOTNumber().startsWith("OT")) {
                return new OrderOutputTrackNumberExcelImport(StringsUtil.getNumberAndCharPattern(orderOutputTrackNumberExcelImport.getOrderOTNumber()), orderOutputTrackNumberExcelImport.getTrackNumber());
            } else {
                return new OrderOutputTrackNumberExcelImport(orderOutputTrackNumberExcelImport.getOrderOTNumber(), orderOutputTrackNumberExcelImport.getTrackNumber());
            }
        }).collect(Collectors.groupingBy(OrderOutputTrackNumberExcelImport::getOrderOTNumber));
        for (String orderNumer : mapCollect.keySet()) {
            OrderOutputTrackNumberExcelImport excelData = null;
            List<OrderOutputTrackNumberExcelImport> orderOutputTrackNumberExcelImports = mapCollect.get(orderNumer);
            if (orderOutputTrackNumberExcelImports == null) continue;
            if (orderOutputTrackNumberExcelImports.size() > 0) {
                excelData = orderOutputTrackNumberExcelImports.get(0);
            }
            Long orderId = 0L;
            if (excelData == null) continue;
            if (orderNumer == null) continue;
//            if (excelData.getTrackNumber().endsWith("0000")) {
//                orderNumbers.add(orderNumer + "运单号异常" + excelData.getTrackNumber());
//                continue;
//            }
            excelData.setOrderOTNumber(orderNumer.trim());
            if (excelData.getTrackNumber() == null) {
                orderNumbers.add(StringsUtil.createI18Message(SysConstant.ORDER_TRACK_NUMBER_NULL, orderNumer));
                continue;
            }
//            if (mapDuplicate.containsKey(excelData.getTrackNumber())) {
//                orderNumbers.add(StringsUtil.createI18Message(SysConstant.ORDER_LINE_NUMBER_REPEAT, (i + 1), orderNumer));
//                continue;
//            }
            if (orderNumer.trim().startsWith("OT")) {
                orderId = Long.parseLong(orderNumer.substring(10));
            }
            excelData.setTrackNumber(excelData.getTrackNumber().trim());
            LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper();
//            wrapper.eq(OrderOutputDo::getStorageId, storageId);
            OrderOutputDo outputDo = dao.selectById(orderId);
            if (outputDo == null) {

                wrapper = new LambdaQueryWrapper<>();
                wrapper.or(orderWrapper -> {
                    orderWrapper.eq(OrderOutputDo::getStatus, DicBusinessItemConstant.outWaitSendOut);
                    orderWrapper.eq(OrderOutputDo::getOrderNo, orderNumer).or().like(OrderOutputDo::getReceiverName, orderNumer.replaceAll(" ", "%").replaceAll("　", "%"));
                });
                wrapper.and(orderQueryWrapper -> {
                    orderQueryWrapper.eq(OrderOutputDo::getStatus, DicBusinessItemConstant.outWaitSendOut).or().eq(OrderOutputDo::getStatus, DicBusinessItemConstant.orderCutOff);
                });
                wrapper.orderByAsc(OrderOutputDo::getCreateTime);
                wrapper.last("limit 1");
                outputDo = dao.selectOne(wrapper);
            }
            if (outputDo != null && !excelData.getTrackNumber().equals(outputDo.getTrackNumber())) {
                if (outputDo.getStatus().equals(DicBusinessItemConstant.outCreateCheckState)) {
                    orderNumbers.add(StringsUtil.createI18Message(SysConstant.ORDER_STATUS_NOT_CHECK, orderNumer));
                    continue;
//                    outputDo.setTrackNumber(excelData.getTrackNumber());
//                    outputDo.setUpdateBy(userid);
//                    outputDo.setUpdateTime(new Date());
//                    dao.updateById(outputDo);
//
//                    operateRecordDao.operateAddRecordAndValue(SysConstant.OPERATE_UPLOAD_NUMBER, outputDo.getTrackNumber(),
//                            outputDo.getId(), userid, 3);
                } else if (!outputDo.getStatus().equals(DicBusinessItemConstant.alreadyPickUp) && !outputDo.getStatus().equals(DicBusinessItemConstant.waitingPickUp) && !outputDo.getStatus().equals(DicBusinessItemConstant.orderCutOff) && !outputDo.getStatus().equals(DicBusinessItemConstant.problemShipment) && !DicBusinessItemConstant.outWaitSendOut.equals(outputDo.getStatus())) {
                    //批量导入不覆盖旧单号
//                    orderNumbers.add(StringsUtil.createI18Message(SysConstant.ORDER_STATUS_NOT_CHECK,orderNumer));
//                    outputDo.setTrackNumber(excelData.getTrackNumber());
//                    outputDo.setUpdateBy(userid);
//                    outputDo.setUpdateTime(new Date());
//                    dao.updateById(outputDo);
//                    operateRecordDao.operateAddRecordAndValue(SysConstant.OPERATE_UPLOAD_NUMBER, outputDo.getTrackNumber(),
//                            outputDo.getId(), userid, 3);
                    continue;
                }
                if (outputDo.getStatus().equals(DicBusinessItemConstant.orderCutOff)) {
                    //截单状态也要更新运单号
                    orderNumbers.add(StringsUtil.createI18Message(SysConstant.ORDER_STATUS_CUTOFF, orderNumer));
                    outputDo.setTrackNumber(excelData.getTrackNumber());
                    outputDo.setUpdateBy(userid);
                    outputDo.setUpdateTime(new Date());
                    dao.updateById(outputDo);
                    operateRecordDao.operateAddRecordAndValue(SysConstant.OPERATE_UPLOAD_NUMBER, outputDo.getTrackNumber(), outputDo.getId(), userid, 3);
                    continue;
                }
                if (storageId == 5) {
                    outputDo.setTrackNumber(excelData.getTrackNumber());
                    outputDo.setUpdateTime(new Date());
                    outputDo.setUpdateBy(userid);
                }

                if (outputDo.getStatus().equals(DicBusinessItemConstant.alreadyPickUp) || DicBusinessItemConstant.waitingPickUp.equals(outputDo.getStatus())) {
                    if (storageId == 5) {//SKL不复核直接发货
                        SendRes sendRes = dealwithOrderSendOutNotException(outputDo, userid);
                        if (sendRes.getCode() != 200) {
                            orderNumbers.add(orderNumer + sendRes.getMsgI18());
                            continue;
                        }
                        this.calFeeAfterSend(outputDo, userid);
                    } else {
//                        orderListSuccess.put(outputDo.getId(), excelData.getTrackNumber());
                        orderListSuccess.put(outputDo.getId(), orderNumer);
                    }
                }
//                else if (DicBusinessItemConstant.waitingPickUp.equals(outputDo.getStatus())) {
//                    //待拣货发货 先去锁定库存，再去发货
//                    StockPickUpDo pickUpDo = stockPickUpDao.selectById(outputDo.getPickUpId());
//                    if (pickUpDo == null) {
//                        orderNumbers.add(orderNumer + StringsUtil.createI18Message(SysConstant.FbaOrder_Pickup_NotMatch));//未匹配到拣货单
//                        continue;
//                    }
//                    try {
//                        stockPickUpService.finishPickUp(pickUpDo, new HashSet<>(), userid, outputDo.getId());
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                        orderNumbers.add(orderNumer + e.getMessage());
//                        continue;
//                    }
//                    if (storageId == 5) {
//                        SendRes sendRes = dealwithOrderSendOutNotException(outputDo, userid);
//                        if (sendRes.getCode() != 200) {
//                            orderNumbers.add(orderNumer + sendRes.getMsgI18());
//                            continue;
//                        }
//                        this.calFeeAfterSend(outputDo, userid);
//                    } else {
//                        orderListSuccess.put(outputDo.getId(), excelData.getTrackNumber());
//                    }
//                }
                else if (outputDo.getStatus().equals(DicBusinessItemConstant.problemShipment)) {
                    //问题件只算费用，不发货
//                    orderListSuccess.put(outputDo.getId(), excelData.getTrackNumber());
                    orderListSuccess.put(outputDo.getId(), orderNumer);
                } else if (DicBusinessItemConstant.outWaitSendOut.equals(outputDo.getStatus())) {
                    //已打单 直接发货
                    if (storageId == 5) {
                        BatchPickUpReq pickUpReq = new BatchPickUpReq();
                        pickUpReq.setIds(Arrays.asList(outputDo.getId()));
                        List<BatchPickUpRes> resList = new ArrayList<>();
                        try {
                            if (outputDo.getPickUpId() == null) {
                                //获取出库推荐库位
                                PickUpRes res = this.batchPickUpNotException(pickUpReq, userid, outputDo.getCompanyId());
                                if (res.getCode() != 200) {
                                    orderNumbers.add(orderNumer + StringsUtil.createI18Message(SysConstant.Product_Stock_NotEnough));
                                    continue;
                                }
                                this.sendWhenOutWaitSendOut(res.getResList().get(0).getPositionAndNumberList(), outputDo, userid);
//                            outputDo.setPickUpId(0L);//0代表已发未拣货
//                            dao.updateById(outputDo);
                            } else {
                                //扣旧表库存
                                SendRes sendRes = dealwithOrderSendOutNotException(outputDo, userid);
                                if (sendRes.getCode() != 200) {
                                    orderNumbers.add(orderNumer + sendRes.getMsgI18());
                                    continue;
                                }
                            }
                            this.calFeeAfterSend(outputDo, userid);
                        } catch (Exception e) {
                            e.printStackTrace();
                            orderNumbers.add(orderNumer + StringsUtil.createI18Message(SysConstant.Product_Stock_NotEnough));
                            continue;
                        }
                    } else {
//                        orderListSuccess.put(outputDo.getId(), excelData.getTrackNumber());
                        orderListSuccess.put(outputDo.getId(), orderNumer);
                    }
                }
                totalCount++;

            } else {
                orderNumbers.add(orderNumer + StringsUtil.createI18Message(SysConstant.ORDER_NOT_EXIST_OR_HAS_OUT));
            }
        }
//        this.confirmSentOut(orderListSuccess, userid);
        this.orderToCheck(orderListSuccess, mapCollect, userid);
        map.put("count", totalCount);
        map.put("error", orderNumbers);
        map.put("success", orderListSuccess);
        return map;
    }

    /**
     * 导入快递单号之后  给用户确认是否发货
     *
     * @param orderListSuccess
     * @param userid
     */
    @Override
    public void confirmSentOut(List<Long> orderListSuccess, Long userid) {
        threadPoolTaskExecutor.execute(() -> {
            for (int i = 0; i < orderListSuccess.size(); i++) {
                OrderOutputDo outputDo = dao.selectById(orderListSuccess.get(i));
                try {
                    double total = dealwithOrderSendOutShipFeeFix(outputDo, 1, userid);
                    mCostService.add(0, outputDo.getOrderOutputNumber() + "订单出库", total, outputDo.getShopId(), outputDo.getCompanyId(), outputDo.getId());
                } catch (Exception e) {
                    e.printStackTrace();
                    outputDo.setStatus(DicBusinessItemConstant.problemShipment);
                    updateById(outputDo);
                }
                //日志操作
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_SEND_ORDER, outputDo.getId(), userid, 3);
//                operateRecord2("发货了出库订单", outputDo.getId(), userid);
            }
        });
    }

    @Override
    public void orderToCheck(Map<Long, String> orderListSuccess, Map<String, List<OrderOutputTrackNumberExcelImport>> mapCollect, Long userid) {
        if (orderListSuccess.size() < 1) return;
        Map<Long, String> listSuccess = new HashMap<>();
        for (Long id : orderListSuccess.keySet()) {
            OrderOutputDo outputDo = dao.selectById(id);
            if (outputDo == null) {
                continue;
            }
            String trackNumber = "";
            StringBuilder trackNumberOperate = new StringBuilder();
            List<OrderOutputTrackNumberExcelImport> trackNumberExcelImportList = mapCollect.get(orderListSuccess.get(id));

            List<OrderOutputPackageDetailDo> packageDetailDoList = packageDetailDao.selectList(new LambdaQueryWrapper<OrderOutputPackageDetailDo>().eq(OrderOutputPackageDetailDo::getOrderOutputId, outputDo.getId()));
            if (trackNumberExcelImportList.size() > 0) {
                trackNumber = trackNumberExcelImportList.get(0).getTrackNumber();
                if (trackNumberExcelImportList.size() == packageDetailDoList.size()) {
                    for (int i = 0; i < packageDetailDoList.size(); i++) {
                        OrderOutputPackageDetailDo detailDo = packageDetailDoList.get(i);
                        detailDo.setTrackNumber(trackNumberExcelImportList.get(i).getTrackNumber());
                        detailDo.setTrackId(outputDo.getTrackId());
                        detailDo.setUpdateTime(new Date());
                        detailDo.setUpdateBy(userid);
                        packageDetailDao.updateById(detailDo);
                        if (trackNumberOperate.length() > 0) trackNumberOperate.append(",");
                        trackNumberOperate.append(trackNumberExcelImportList.get(i).getTrackNumber());
                    }
                } else {
                    for (int i = 0; i < packageDetailDoList.size(); i++) {
                        OrderOutputPackageDetailDo detailDo = packageDetailDoList.get(i);
                        detailDo.setTrackId(outputDo.getTrackId());
                        detailDo.setUpdateTime(new Date());
                        detailDo.setUpdateBy(userid);
                        if (i < trackNumberExcelImportList.size()) {
                            if (trackNumberOperate.length() > 0) {
                                trackNumberOperate.append(",");
                            }
                            trackNumberOperate.append(trackNumberExcelImportList.get(i).getTrackNumber());
                            detailDo.setTrackNumber(trackNumberExcelImportList.get(i).getTrackNumber());
                        } else {
                            detailDo.setTrackNumber(trackNumberExcelImportList.get(trackNumberExcelImportList.size() - 1).getTrackNumber());
                        }
                        packageDetailDao.updateById(detailDo);
                    }
                }
            }
            outputDo.setStatus(DicBusinessItemConstant.outToCheck);
            outputDo.setTrackNumber(trackNumber);
            outputDo.setUpdateTime(new Date());
            outputDo.setUploadTime(new Date());
            outputDo.setUpdateBy(userid);
            dao.updateById(outputDo);
            listSuccess.put(id, trackNumberOperate.toString());
        }
        threadPoolTaskExecutor.execute(() -> {
            for (Long id : listSuccess.keySet()) {
                operateRecordDao.operateAddRecordAndValue(SysConstant.OPERATE_UPLOAD_NUMBER, listSuccess.get(id), id, userid, 3);
//                operateRecord2(String.format("上传了出库订单,单号：%s", orderListSuccess.get(id)), id, userid);
            }
        });
    }

    private void dealwithOrderSendOut(OrderOutputDo outputDo, Long userId) {
        SendRes res = this.dealwithOrderSendOutNotException(outputDo, userId);
        if (res.getCode() != 200) {
            throw new BizException(res.getMsg());
        }
    }


    private SendRes dealwithOrderSendOutNotException(OrderOutputDo outputDo, Long userId) {

        //查询 拣货单
        SendRes sendRes = new SendRes();
        StockPickUpDo pickUpDo = stockPickUpDao.selectById(outputDo.getPickUpId());
        if (pickUpDo == null) {
            sendRes.setCode(500);
            sendRes.setMsg(SysConstant.FbaOrder_Pickup_NotMatch);
            return sendRes;
        }
        LambdaQueryWrapper<OrderOutputProductDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderOutputProductDo::getOrderId, outputDo.getId());
        List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper);

        for (OrderOutputProductDo orderOutputProductDo : productDoList) {
            sendRes = productOutService.dealStockAfterSendOut(outputDo.getId(), outputDo.getOrderOutputNumber(), StaticDict.Product_Flowing_Type.Output.getValue(), StaticDict.Product_Flowing_Type.Output.getValue(), orderOutputProductDo.getCount(), orderOutputProductDo.getProductId(), outputDo.getStorageId(), outputDo.getShopId(), pickUpDo.getId(), outputDo.getCompanyId(), userId);
            if (sendRes.getCode() != 200) {
//                throw new BizException(sendRes.getMsg());
                return sendRes;
            }

            //操作旧表库存
            LambdaQueryWrapper<StockRecordDo> stockWrapper = new LambdaQueryWrapper<>();
            stockWrapper.eq(StockRecordDo::getProductInfoId, orderOutputProductDo.getProductId()).eq(StockRecordDo::getStorageId, outputDo.getStorageId()).eq(StockRecordDo::getShopId, outputDo.getShopId());
            StockRecordDo stockRecordDo = mStockRecordDao.selectOne(stockWrapper);

            if (stockRecordDo == null) {
                sendRes.setCode(500);
                sendRes.setMsg(SysConstant.Stock_Old_NotExist);
                return sendRes;
            }
            mStockRecordDao.updateStockById(stockRecordDo.getId(), orderOutputProductDo.getCount());

            threadPoolTaskExecutor.execute(() -> {
                mStockLogService.saveAutoSendOutLog(orderOutputProductDo.getProductId(), outputDo.getShopId(), outputDo.getStorageId(), -orderOutputProductDo.getCount(), stockRecordDo.getCanSellCount() - orderOutputProductDo.getCount(), outputDo.getCompanyId(), userId, outputDo.getOrderNo());
            });

        }
        sendRes.setCode(200);
        return sendRes;
    }

    /**
     * 捆包商品出库时使用
     *
     * @param capacity
     * @param number
     * @return
     */
    //对于耗材费用的计算 传数量 和尺寸大小
    private Double checkOutFee(Double capacity, int number) {
        if (capacity > 105L) return 0D;
        Double price = 0D;
        LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DicBusinessItemDo::getDicBusinessId, 32L);
        List<Long> dicIds = dicBusinessItemDao.selectList(wrapper).stream().map(DicBusinessItemDo::getId).collect(Collectors.toList());
        LambdaQueryWrapper<StorageServiceProjectDo> sspWrapper = new LambdaQueryWrapper<>();
        sspWrapper.in(StorageServiceProjectDo::getType, dicIds);
        List<StorageServiceProjectDo> storageServiceProjectDos = storageServiceProjectDao.selectList(sspWrapper);
        for (StorageServiceProjectDo storageServiceProjectDo : storageServiceProjectDos) {
            if (storageServiceProjectDo.getCapacity() > capacity) {
                price = (double) storageServiceProjectDo.getPrice() * number;
                break;
            }
            price = 0D;
        }
        return price;
    }

    /**
     * 一般是单个商品出库时使用
     *
     * @param cId      耗材id
     * @param capacity 尺寸
     * @param number   数量
     * @return
     */
    //对于耗材费用的计算 传数量 和尺寸大小
    private Double checkOutFee(Long cId, Double capacity, int number) {
        if (cId == null || cId == 1) return 0D;
        Double price = 0D;
        if (cId < 1) {
            if (capacity > 105) {
                return 0D;
            }
            LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DicBusinessItemDo::getDicBusinessId, 32L);
            List<Long> dicIds = dicBusinessItemDao.selectList(wrapper).stream().map(DicBusinessItemDo::getId).collect(Collectors.toList());
            LambdaQueryWrapper<StorageServiceProjectDo> sspWrapper = new LambdaQueryWrapper<>();
            sspWrapper.in(StorageServiceProjectDo::getType, dicIds);
            List<StorageServiceProjectDo> storageServiceProjectDos = storageServiceProjectDao.selectList(sspWrapper);
            for (StorageServiceProjectDo storageServiceProjectDo : storageServiceProjectDos) {
                if (storageServiceProjectDo.getCapacity() > capacity) {
                    price = (double) storageServiceProjectDo.getPrice() * number;
                    break;
                }
                price = 0D;
            }
        } else {
            StorageServiceProjectDo storageServiceProjectDo = storageServiceProjectDao.selectById(cId);
            price = (double) storageServiceProjectDo.getPrice() * number;
        }
        return price;
    }

    /**
     * @param orderNumbers
     * @param type         0 只收运费 1 收运费和操作费
     */
    @Override
    public void shipfeeFix(List<String> orderNumbers, int type, Long userId) {
        for (String orderNumber : orderNumbers) {
            LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OrderOutputDo::getOrderOutputNumber, orderNumber);
            OrderOutputDo outputDo = dao.selectOne(wrapper);
            if (outputDo == null) continue;
            threadPoolTaskExecutor.execute(() -> {
                double totalFee = dealwithOrderSendOutShipFeeFix(outputDo, type, userId);
                mCostService.add(0, outputDo.getOrderOutputNumber() + "订单出库补收快递费", totalFee, outputDo.getShopId(), outputDo.getCompanyId(), outputDo.getId());
            });
        }
    }

    @Override
    public double dealwithOrderSendOutShipFeeFix(OrderOutputDo outputDo, int type, Long userId) {
        double[] size;
        double shipFee = 0;
        double originalShipFee = 0;
        double operateFee = 0;
        double taxFee = 0;
        double outFee = 0;
        int packageCount = 1;
        int totalCount = 0;
        LambdaQueryWrapper<OrderOutputPackageDo> packageWrapper = new LambdaQueryWrapper<>();
        packageWrapper.eq(OrderOutputPackageDo::getOrderOutputId, outputDo.getId());
        List<OrderOutputPackageDo> packageDoList = packageDao.selectList(packageWrapper);

        LambdaQueryWrapper<OrderOutputProductDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderOutputProductDo::getOrderId, outputDo.getId());
        List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper);
        for (OrderOutputProductDo orderOutputProductDo : productDoList) {
            totalCount = totalCount + orderOutputProductDo.getCount();
        }
        //todo 计费
        StorageDo storageDo = storageDao.selectById(outputDo.getStorageId());
        CompanyDo companyDo = mCompanyDao.selectById(outputDo.getCompanyId());

        if ("1".equals(storageDo.getSupportShip())) {//支持捆包
            size = mShipPriceService.getMulitSkuSize(productDoList);
            ShipPriceDo shipPrices = null;
            //todo 多包裹处理
            if (verifyMaxSize(productDoList, size, outputDo.getStorageId()) && totalCount > 1 && !DicBusinessItemConstant.xinongExpress.equals(outputDo.getTrackId())) {
                //捆包完多个个包裹
//                List<OrderOutputPackageDetailDo> packageDoListCount = getPackageSizeInfoCount(productDoList, size, outputDo.getCompanyId(), outputDo.getStorageId());
                LambdaQueryWrapper<OrderOutputPackageDetailDo> lambdaDeleteWrapper = new LambdaQueryWrapper<>();
                lambdaDeleteWrapper.eq(OrderOutputPackageDetailDo::getPackageId, packageDoList.get(0).getId());
                lambdaDeleteWrapper.eq(OrderOutputPackageDetailDo::getOrderOutputId, outputDo.getId());
                List<OrderOutputPackageDetailDo> packageDetailDoList = packageDetailDao.selectList(lambdaDeleteWrapper);
                if (packageDetailDoList == null || packageDetailDoList.size() < 1) {
                    packageDetailDoList = getPackageSizeInfoCount(productDoList, size, outputDo.getStorageId());
                    //保存 捆包分包详情表
                    for (OrderOutputPackageDetailDo packageDo : packageDetailDoList) {
                        OrderOutputPackageDetailDo detailDo = packageDo;
                        detailDo.setPackageId(packageDoList.get(0).getId());
                        detailDo.setOrderOutputId(outputDo.getId());
                        detailDo.setCount(1);
                        detailDo.setCreateBy(outputDo.getCreateBy());
                        detailDo.setCreateTime(new Date());
                        packageDetailDao.insert(detailDo);
                    }
                }
                for (OrderOutputPackageDetailDo packageDo : packageDetailDoList) {
                    double[] packageSize = mShipPriceService.getSizeOrderDesc(packageDo.getLength(), packageDo.getWidth(), packageDo.getHeight());
                    Long stateId = mRegionService.getStateIdByPostCode(outputDo.getPostCode());
                    shipPrices = mShipPriceService.queryByRegionAndSize(stateId, packageDo.getWeight(), packageDo.getLength() + packageDo.getWidth() + packageDo.getHeight(), packageSize[0], packageSize[1], packageSize[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                    if (shipPrices == null) {
                        //未找到费用信息，请人工处理
                        if (outputDo.getShipFee() != 0D) {
                            shipFee = outputDo.getShipFee();
                            break;
                        } else if (outputDo.getTrackId() == DicBusinessItemConstant.xinongExpress) {
                            //指定快递公司为西浓
                            shipPrices = mShipPriceService.queryByRegionAndSize(stateId, size[3], new BigDecimal(size[0] * size[1] * size[2] * 0.00028).setScale(1, BigDecimal.ROUND_UP).doubleValue(), packageSize[0], packageSize[1], packageSize[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                            shipFee = shipPrices.getPrice();
                        } else {
                            outputDo.setStatus(DicBusinessItemConstant.problemShipment);
                            updateById(outputDo);
                            return 0;
                        }
                    } else {
                        shipFee = shipFee + shipPrices.getPrice();
                        originalShipFee = originalShipFee + shipPrices.getOriginalPrice();
                    }
                    //计算耗材费用
                    if (packageDo.getInCount() > 1 && !outputDo.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox)) {
                        Double capacity = packageDo.getHeight() + packageDo.getWidth() + packageDo.getLength();
                        outFee += checkOutFee(capacity, 1);
                    }

                }
                if (packageDetailDoList.size() == totalCount) {
                    operateFee = mShipPriceService.getMulitSkuOperationFeeNoPackage(productDoList, String.valueOf(outputDo.getCompanyId()));
                } else {
                    operateFee = mShipPriceService.getMulitSkuOperationFee(packageDetailDoList, productDoList, String.valueOf(outputDo.getCompanyId()));
                }
            } else if (!verifyMaxSize(productDoList, size, outputDo.getStorageId()) || totalCount == 1) {
                //捆包完一个包裹
                packageCount = 1;
                shipPrices = mShipPriceService.queryByRegionAndSize(regionService.getStateIdByPostCode(outputDo.getPostCode()), size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                if (shipPrices == null) {
                    //未找到费用信息，请人工处理
                    if (outputDo.getShipFee() != 0D) {
                        shipFee = outputDo.getShipFee();
//                        originalShipFee = shipPrices.getOriginalPrice();
                    } else {
                        outputDo.setStatus(DicBusinessItemConstant.problemShipment);
                        updateById(outputDo);
                        return 0;
                    }
                } else {
                    shipFee = shipPrices.getPrice();
                    originalShipFee = shipPrices.getOriginalPrice();
                }
                //计算耗材费用
                Double capacity = size[0] + size[1] + size[2];
                OrderOutputProductDo orderOutputProductDo = productDoList.get(0);
                ProductInfoDo productInfoDo = productInfoDao.selectById(orderOutputProductDo.getProductId());
                if (productInfoDo != null && !outputDo.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox))
                    if (totalCount <= 1) {//单个商品看商品情况需不需包装
                        outFee += checkOutFee(productInfoDo.getConsumables(), capacity, 1);
                        operateFee = mShipPriceService.getMulitSkuOperationFeeNoPackage(productDoList, String.valueOf(outputDo.getCompanyId()));
                    } else {//多个商品看商品必需包装
                        outFee += checkOutFee(capacity < 100 ? 0L : 1L, capacity, 1);
                        operateFee = mShipPriceService.getMulitSkuOperationFee(null, productDoList, String.valueOf(outputDo.getCompanyId()));
                    }

            } else {//单个物件超大的情况
                if (!DicBusinessItemConstant.xinongExpress.equals(outputDo.getTrackId())) {
                    outputDo.setStatus(DicBusinessItemConstant.problemShipment);
                    updateById(outputDo);
                    return 0;
                }
                //指定快递公司为西浓
                double sizeT = 0;
                double weigth = 0;
                for (OrderOutputProductDo productDo : productDoList) {
                    ProductInfoDo productInfoDo = productInfoDao.selectById(productDo.getProductId());
                    if (productInfoDo == null) continue;
                    double[] size1 = new double[]{productInfoDo.getWidth(), productInfoDo.getHeight(), productInfoDo.getLength() * productDo.getCount(), productInfoDo.getWeight() * productDo.getCount()};
                    sizeT = sizeT + size1[0] * size1[1] * size1[2] * 0.00028;
                    weigth = weigth + size1[3];
                }
                //体积重取大值
                sizeT = Math.max(sizeT, weigth);
                shipPrices = mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(outputDo.getPostCode()), weigth, new BigDecimal(sizeT).setScale(1, BigDecimal.ROUND_UP).doubleValue(), null, null, null, outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                if (shipPrices == null) {
                    //体积重超出
                    while (sizeT > 400) {
                        shipPrices = mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(outputDo.getPostCode()), 400, new BigDecimal(400).setScale(1, BigDecimal.ROUND_UP).doubleValue(), null, null, null, outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                        sizeT = sizeT - 400;
                        if (shipPrices == null) {
                            //未找到费用信息，请人工处理
                            outputDo.setStatus(DicBusinessItemConstant.problemShipment);
                            updateById(outputDo);
                            return 0;
                        } else {
                            shipFee = shipFee + shipPrices.getPrice();
                            originalShipFee = originalShipFee + shipPrices.getOriginalPrice();
                        }
                    }
                    if (sizeT > 0) {
                        shipPrices = mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(outputDo.getPostCode()), 400, new BigDecimal(400).setScale(1, BigDecimal.ROUND_UP).doubleValue(), null, null, null, outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                        shipFee = shipFee + shipPrices.getPrice();
                        originalShipFee = originalShipFee + shipPrices.getOriginalPrice();
                    }
                } else {
                    shipFee = shipPrices.getPrice();
                    originalShipFee = shipPrices.getOriginalPrice();
                }


                //计算耗材费用
                //Double capacity = size[0] + size[1] + size[2];
                //outFee += checkOutFee(productDoList, capacity, 1);
                operateFee = mShipPriceService.getMulitSkuOperationFeeNoPackage(productDoList, String.valueOf(outputDo.getCompanyId()));
            }
        } else {
            if (DicBusinessItemConstant.xinongExpress.equals(outputDo.getTrackId())) {
                double sizeT = 0d;
                double weigth = 0d;
                for (OrderOutputProductDo productDo : productDoList) {
                    ProductInfoDo productInfoDo = productInfoDao.selectById(productDo.getProductId());
                    if (productInfoDo == null) continue;

                    double[] size1 = new double[]{productInfoDo.getWidth(), productInfoDo.getHeight(), productInfoDo.getLength() * productDo.getCount(), productInfoDo.getWeight() * productDo.getCount()};
                    sizeT = sizeT + size1[0] * size1[1] * size1[2] * 0.00028;
                    weigth = weigth + size1[3];
                }
                //体积重取大值
                sizeT = Math.max(sizeT, weigth);
                ShipPriceDo shipPrices = mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(outputDo.getPostCode()), weigth, new BigDecimal(sizeT).setScale(1, BigDecimal.ROUND_UP).doubleValue(), null, null, null, 0, 0, outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                if (shipPrices == null) {
                    //体积重超出
                    while (sizeT > 400) {
                        shipPrices = mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(outputDo.getPostCode()), 400, new BigDecimal(400).setScale(1, BigDecimal.ROUND_UP).doubleValue(), null, null, null, 0, 0, outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                        sizeT = sizeT - 400;
                        if (shipPrices == null) {
                            //未找到费用信息，请人工处理
                            outputDo.setStatus(DicBusinessItemConstant.problemShipment);
                            updateById(outputDo);
                            return 0;
                        } else {
                            shipFee = shipFee + shipPrices.getPrice();
                            originalShipFee = originalShipFee + shipPrices.getOriginalPrice();
                        }
                    }
                    if (sizeT > 0) {
                        shipPrices = mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(outputDo.getPostCode()), 400, new BigDecimal(400).setScale(1, BigDecimal.ROUND_UP).doubleValue(), null, null, null, 0, 0, outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                        shipFee = shipFee + shipPrices.getPrice();
                        originalShipFee = originalShipFee + shipPrices.getOriginalPrice();
                    }
                } else {
                    shipFee = shipPrices.getPrice();
                    originalShipFee = shipPrices.getOriginalPrice();
                }
            } else {
                for (OrderOutputProductDo productDo : productDoList) {
                    ProductInfoDo productInfoDo = productInfoDao.selectById(productDo.getProductId());
                    if (productInfoDo == null) continue;

                    double[] sortSize = mShipPriceService.getSizeOrderDesc(productInfoDo.getWidth(), productInfoDo.getHeight(), productInfoDo.getLength());

                    ShipPriceDo shipPrices = mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(outputDo.getPostCode()), productInfoDo.getWeight(), sortSize[0] + sortSize[1] + sortSize[2], sortSize[0], sortSize[1], sortSize[2], 0, 0, outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion());
                    if (shipPrices == null) {
                        //未找到费用信息，请人工处理
                        if (outputDo.getShipFee() != 0D) {
                            shipFee = outputDo.getShipFee();
                        } else {
                            outputDo.setStatus(DicBusinessItemConstant.problemShipment);
                            updateById(outputDo);
                            return 0;
                        }
                    } else {
                        shipFee = shipFee + shipPrices.getPrice() * productDo.getCount();
                        originalShipFee = originalShipFee + shipPrices.getOriginalPrice() * productDo.getCount();
                    }
                    //计算耗材费用
                    if (productInfoDo.getConsumables() != null && productInfoDo.getConsumables() > 1L && !outputDo.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox)) {
                        Double capacity = (double) (productInfoDo.getWidth() + productInfoDo.getHeight() + productInfoDo.getLength());
                        outFee += checkOutFee(capacity, productDo.getCount());
                    }
                }
            }
            operateFee = mShipPriceService.getMulitSkuOperationFeeNoPackage(productDoList, String.valueOf(outputDo.getCompanyId()));
        }
        outputDo.setShipFee(shipFee);
        outputDo.setOriginShipFee(originalShipFee);
        if (type == 0) {
            operateFee = 0;
        }
        outputDo.setOperateFee(operateFee);
        //耗材费用
        outputDo.setOutFee(outFee);
        //税费公式  一件代发的税费计算  税费=(快递费+出库费+操作费)*0.1
        outputDo.setTaxFee((shipFee + outFee + operateFee) * 0.1);

        double totalFee = outputDo.getShipFee() + outputDo.getOperateFee() + outputDo.getOutFee() + outputDo.getTaxFee();
        if (outputDo.getDiffPrice() != null && outputDo.getDiffPrice() > 0) {
            totalFee += outputDo.getDiffPrice();
        }
        if (outputDo.getStatus().equals(DicBusinessItemConstant.alreadyPickUp) || outputDo.getStatus().equals(DicBusinessItemConstant.problemShipment) || DicBusinessItemConstant.outWaitSendOut.equals(outputDo.getStatus()) || DicBusinessItemConstant.waitingPickUp.equals(outputDo.getStatus()) || DicBusinessItemConstant.outToCheck.equals(outputDo.getStatus())) {
            outputDo.setStatus(DicBusinessItemConstant.outSendOut);
            if (!outputDo.getStatus().equals(DicBusinessItemConstant.problemShipment)) {
                outputDo.setSendTime(new Date());
            }
        }
        updateById(outputDo);
        //发货完成，判断拣货单是否全部完成拣货
//        if (DicBusinessItemConstant.outSendOut.equals(outputDo.getStatus()) && outputDo.getPickUpId() != null) {
//            stockPickUpService.finishPickUpAfter(outputDo.getPickUpId(), userId);
//        }
        return totalFee;
    }

    private boolean verifyMaxSize(List<OrderOutputProductDo> productDoList, double[] size, Long storageId) {
        double[] sizeLast = new double[4];
        boolean iMulti = false;
        for (OrderOutputProductDo productDo : productDoList) {
            ProductInfoDo productBean = productInfoDao.selectById(productDo.getProductId());
            if (productBean == null) continue;
            double[] sizeP = mShipPriceService.getSizeOrderDesc(productBean.getWidth(), productBean.getHeight(), productBean.getLength());
            if ((productDoList.size() > 0 || productDo.getCount() > 0) && inNoPackageProductList(productDo.getProductId())) {
                iMulti = true;
            } else if ((sizeLast[0] != 0 && sizeLast[0] != sizeP[0]) || (sizeLast[1] != 0 && sizeLast[1] != sizeP[1])) {
                //如果当前SKU和上一个SKU长宽 边不等，则不能捆包，返回true
                iMulti = true;
            }
            sizeLast = new double[]{sizeP[0], sizeP[1], sizeP[2], productBean.getWeight()};
        }
        return verifyMaxSize(size, iMulti, storageId);
    }

    private boolean verifyMaxSize(double[] size, boolean isMulti, Long storageId) {
        if (isMulti) {
            //多尺寸SKU
            return size[0] + size[1] + size[2] > SysConstant.OUT_MAX_MUTIL_PACKAGE_SIZE || size[3] > SysConstant.OUT_MAX_MUTIL_PACKAGE_WEIGHT;
        } else if (storageId == 12) {
            //单尺寸SKU
            return size[0] + size[1] + size[2] > 120 || size[3] > 15;
        } else {
            //单尺寸SKU
            return size[0] + size[1] + size[2] > SysConstant.OUT_MAX_SINGLE_PACKAGE_SIZE || size[3] > SysConstant.OUT_MAX_SINGLE_PACKAGE_WEIGHT;
        }
    }

    private List<Long> getNoPackageProductList() {
        List<Long> productList = new ArrayList<>();
        productList.addAll(Arrays.asList(11076L, 11077L, 11615L, 12625L, 13288L, 13905L, 13924L, 13925L, 13931L));
//        return productInfoDao.selectList(new QueryWrapper<>().eq());
        return productList;
    }


    public double[] getMaxPackageSize(double[] size, Long storageId, List<OrderOutputProductDo> productDoList) {
        int sizeType = this.jugSizeType(size, storageId, productDoList);
        List<OrderOutputPackageDetailDo> packageDoListCount = new ArrayList<>();
        if (sizeType == 0) {
            packageDoListCount = this.getPackageSizeInfoCount(productDoList, size, storageId);
        }
        double[] packageSize = new double[5];
        if (packageDoListCount.size() == 0) {
            packageSize[0] = size[0];
            packageSize[1] = size[1];
            packageSize[2] = size[2];
            packageSize[3] = size[3];
            packageSize[4] = 1;
        } else {
            //捆包多尺寸信息，选最大尺寸展示
            for (OrderOutputPackageDetailDo orderOutputPackageDo : packageDoListCount) {
                packageSize[0] = (Math.max(orderOutputPackageDo.getLength(), packageSize[0]));
                packageSize[1] = (Math.max(orderOutputPackageDo.getWidth(), packageSize[1]));
                packageSize[2] = (Math.max(orderOutputPackageDo.getHeight(), packageSize[2]));
                packageSize[3] = (Math.max(orderOutputPackageDo.getWeight(), packageSize[3]));
                packageSize[4] = (packageDoListCount.size());
            }
        }
        StorageDo storageDo = storageDao.selectById(storageId);
        if ("0".equals(storageDo.getSupportShip())) {
            ProductInfoDo productInfoDo = productInfoDao.selectById(productDoList.get(0).getProductId());
            if (productInfoDo != null) {
                packageSize[0] = productInfoDo.getLength();
                packageSize[1] = productInfoDo.getLength();
                packageSize[2] = productInfoDo.getLength();
                packageSize[3] = productInfoDo.getLength();
                packageSize[4] = productDoList.stream().mapToInt(OrderOutputProductDo::getCount).sum();
            }
        }
        double[] sortSize = mShipPriceService.getSizeOrderDesc(packageSize[0], packageSize[1], packageSize[2]);
        packageSize[0] = sortSize[0];
        packageSize[1] = sortSize[1];
        packageSize[2] = sortSize[2];
        return packageSize;
    }


    private String updateTrackId(OrderOutputDo outputDo) {
//        threadPoolTaskExecutor.execute(() -> {
        List<OrderOutputProductDo> productDoList = new ArrayList<>();
        List<OrderOutputPackageDo> packageDoList = new ArrayList<>();
        int count = 0;
        do {
            QueryWrapper<OrderOutputProductDo> wrapper = new QueryWrapper<>();
            wrapper.eq("order_id", outputDo.getId());
            productDoList = productDao.selectList(wrapper);
            QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
//        outputDo.setOriginShipFee((int) shipPrices.get(0).getPrice());
            wrapper1.eq("order_output_id", outputDo.getId());
            packageDoList = packageDao.selectList(wrapper1);
            count++;
            if (count > 20) return StringsUtil.createI18Message(SysConstant.ORDER_CREATE_ERROR);
            if (count > 3) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } while (productDoList.size() < 1 || packageDoList.size() < 1);

        double[] size = mShipPriceService.getMulitSkuSize(productDoList);
        StorageDo storageDo = storageDao.selectById(outputDo.getStorageId());
        List<ShipPriceDo> shipPrices = new ArrayList<>();
        CompanyDo companyDo = mCompanyDao.selectById(outputDo.getCompanyId());
        int sizeType = this.jugSizeType(size, outputDo.getStorageId(), productDoList);
        //计算最大的捆包尺寸
        if (packageDoList.size() == 1) {
            OrderOutputPackageDo packageDo = packageDoList.get(0);
            double[] packageSize = this.getMaxPackageSize(size, outputDo.getStorageId(), productDoList);
            packageDo.setLength(packageSize[0]);
            packageDo.setWidth(packageSize[1]);
            packageDo.setHeight(packageSize[2]);
            packageDo.setWeight(packageSize[3]);
            packageDo.setCount((int) packageSize[4]);
            packageDao.updateById(packageDo);
        }
        if ("1".equals(storageDo.getSupportShip())) {
            if (outputDo.getTrackId() != null && outputDo.getTrackId() != 0) {
                ShipPriceDo priceDo;
                if (sizeType == 3) {
                    priceDo = this.queryByRegionAndSize(regionService.getStateIdByPostCode(outputDo.getPostCode()), size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion(), productDoList.get(0).getProductId());
                } else if (sizeType == 2) {//捆包
                    priceDo = mShipPriceService.queryByRegionAndSize(regionService.getStateIdByPostCode(outputDo.getPostCode()), size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion(), 0);
                } else {
                    priceDo = mShipPriceService.queryByRegionAndSize(regionService.getStateIdByPostCode(outputDo.getPostCode()), packageDoList.get(0).getWeight(), packageDoList.get(0).getLength() + packageDoList.get(0).getWidth() + packageDoList.get(0).getHeight(), packageDoList.get(0).getLength(), packageDoList.get(0).getWidth(), packageDoList.get(0).getHeight(), outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), outputDo.getTrackId(), companyDo.getShipPriceVersion(), 0);
                }
                if (priceDo == null) {
                    outputDo.setTrackId(null);
                    return updateTrackId(outputDo);
                }
                outputDo.setStatus(DicBusinessItemConstant.outCreateCheckState);
            } else {
                if (sizeType == 3) {
                    shipPrices = this.queryByRegionAndSize(outputDo.getPostCode(), size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), companyDo.getShipPriceVersion(), productDoList.get(0).getProductId());
                } else if (sizeType == 2) {
                    shipPrices = mShipPriceService.queryByRegionAndSize(outputDo.getPostCode(), size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), companyDo.getShipPriceVersion(), 0);
                } else {//计算最大的包裹尺寸哪个最划算
                    double[] packageSize = mShipPriceService.getSizeOrderDesc(packageDoList.get(0).getLength(), packageDoList.get(0).getWidth(), packageDoList.get(0).getHeight());
                    shipPrices = mShipPriceService.queryByRegionAndSize(regionService.getStateIdByPostCode(outputDo.getPostCode()), packageDoList.get(0).getWeight(), packageSize[0] + packageSize[1] + packageSize[2], packageSize[0], packageSize[1], packageSize[2], outputDo.getCod(), outputDo.getShipmentType(), outputDo.getStorageId(), companyDo.getShipPriceVersion(), 0);
                }
                if (shipPrices == null || shipPrices.size() < 1) {
                    //未找到费用信息，请人工处理
                    outputDo.setStatus(DicBusinessItemConstant.outCreateCheckState);
                    outputDo.setTrackId(DicBusinessItemConstant.sagawaExpress);
                    if (productDoList.size() == 1 && productDoList.get(0).getCount() == 1 && (size[0] + size[1] + size[2] > 260 || size[3] > 50)) {
                        outputDo.setTrackId(DicBusinessItemConstant.xinongExpress);
                        outputDo.setStatus(DicBusinessItemConstant.outCreateCheckState);
                    }
                } else {
                    if (outputDo.getTrackId() == null || outputDo.getTrackId() == 0)
                        outputDo.setTrackId(mDimenDao.selectById(shipPrices.get(0).getDimensId()).getTrackId());
                    outputDo.setStatus(DicBusinessItemConstant.outCreateCheckState);
                }
            }

            //货到付款只支持mtb
            if ((outputDo.getStorageId() == 10 || outputDo.getStorageId() == 11) && outputDo.getCod() != null && outputDo.getCod() != 0) {
                outputDo.setTrackId(DicBusinessItemConstant.sagawaExpress);
            }
        } else {
            outputDo.setStatus(DicBusinessItemConstant.outCreateCheckState);
            outputDo.setTrackId(DicBusinessItemConstant.sagawaExpress);
        }
        if (((outputDo.getCompanyId().equals(14L) && outputDo.getStorageId().equals(10L))
                || productDoList.size() > 1 || productDoList.stream().mapToInt(OrderOutputProductDo::getCount).sum() > 1)
                && (DicBusinessItemConstant.yamatoExpress.equals(outputDo.getTrackId()))) {
            outputDo.setTrackId(DicBusinessItemConstant.yamatoExpressNew);
        }
        if ((DicBusinessItemConstant.yamatoExpress.equals(outputDo.getTrackId())
                || DicBusinessItemConstant.yamatoExpressSmall.equals(outputDo.getTrackId())) &&
                isSeinoTrack(productDoList)) {
            outputDo.setTrackId(DicBusinessItemConstant.sagawaExpress);
        }
        updateById(outputDo);
        return null;
    }


    /**
     * //黑猫临时切换成佐川发货
     *
     * @param productDoList
     * @return
     */
    private boolean isSeinoTrack(List<OrderOutputProductDo> productDoList) {
        String s = "4753,4939,5202,5428,7187,7188,8292,8294,8940,11076,11077,11078,11079,12625,12642,12643,12644,12645,12646," +
                "12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,13051,13079," +
                "13288,13414,13439,13593,13594,13609,13905,13924,13925,13967,14517,14606,14607,14859,14860,14861,14862,14863," +
                "14864,14865,15058,15143,15144,15145,15152,15221,15222,15257,15258,15259,15260,15355,15749,16037,16039,16047," +
                "16053,16361,16440,16742,16743,17419,15765";
        List<String> strings = Arrays.stream(s.split(",")).collect(Collectors.toList());
        for (OrderOutputProductDo productDo : productDoList) {
            if (strings.contains(productDo.getProductId() + "")) return true;
        }
        return false;
    }

    public ShipPriceDo queryByRegionAndSize(Long stateId, double weight, double size, Double longest, Double minor, Double shortest, Integer cod, Integer shipmentType, Long storageId, Long trackId, int version, long productId) {
        ProductInfoDo productInfoDo = productInfoDao.selectObject(productId);
//        return mShipPriceService.queryByRegionAndSize(stateId, weight, size, longest, minor, shortest, cod, shipmentType, storageId, trackId, version, productInfoDo.getConsumables() > 1 ? 0 : 1);
        return mShipPriceService.queryByRegionAndSize(stateId, weight, size, longest, minor, shortest, cod, shipmentType, storageId, trackId, version, productInfoDo.getConsumables() == 0 || productInfoDo.getConsumables() > 1 ? 0 : 1);
    }


    public List<ShipPriceDo> queryByRegionAndSize(String postCode, double weight, double size, Double longest, Double minor, Double shortest, Integer cod, Integer shipmentType, Long storageId, int version, long productId) {
        ProductInfoDo productInfoDo = productInfoDao.selectObject(productId);
        return mShipPriceService.queryByRegionAndSize(mRegionService.getStateIdByPostCode(postCode), weight, size, longest, minor, shortest, cod, shipmentType, storageId, version, productInfoDo.getConsumables() == 0 || productInfoDo.getConsumables() > 1 ? 0 : 1);
    }


    public int jugSizeType(double[] size, Long storageId, List<OrderOutputProductDo> productDoList) {
        boolean flag = verifyMaxSize(productDoList, size, storageId);//判断捆包超不超过尺寸
        if (flag) {//捆包尺寸超大
            return 0;
        } else {
            if ((productDoList.size() == 1 && productDoList.get(0).getCount() == 1)) {//一单一件
                return 3;
            } else {//一单多件
                return 2;
            }
        }
    }


    /**
     * 判断 是否是 黑猫小包的size
     *
     * @return
     */
    @Override
    public boolean yamatoExpressSmallSize(double[] size, Long storageId, Integer cod, Integer shipmentType) {
        return size[0] + size[1] + size[2] < 60 && size[3] < 1 && size[0] < 31.2 && size[1] < 22.8 && size[2] < 2.5 && (storageId == 10 || storageId == 11) && (cod == null || cod == 0) && (shipmentType == null || shipmentType == 0);
    }

    private void updateFBATrackId(OrderOutputDo outputDo) {
        List<OrderOutputPackageDo> packageDoListCount = new ArrayList<>();
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("order_id", outputDo.getId());
        List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper);
    }
//
//    /**
//     * 获取包裹捆包信息
//     *
//     * @param productDoList
//     * @param size
//     * @param storageId
//     * @return
//     */
//    private List<OrderOutputPackageDo> getPackageSizeInfoCount(List<OrderOutputProductDo> productDoList, double[] size, Long companyId, Long storageId) {
//        size = new double[4];
//        List<OrderOutputPackageDo> packageDoList = new ArrayList<>();
//        for (OrderOutputProductDo productDo :
//                productDoList) {
//            for (int i = 0; i < productDo.getCount(); i++) {
//                double[] sizeTemp = new double[]{size[0], size[1], size[2], size[3]};
//                if (verifyMaxSize(mShipPriceService.countSameSkuSize(size, productDo.getProductId(), 1), companyId, storageId)) {
//                    OrderOutputPackageDo packageDo = new OrderOutputPackageDo();
//                    packageDo.setLength(sizeTemp[0] == 0 ? size[0] : sizeTemp[0]);
//                    packageDo.setWidth(sizeTemp[1] == 0 ? size[1] : sizeTemp[1]);
//                    packageDo.setHeight(sizeTemp[2] == 0 ? size[2] : sizeTemp[2]);
//                    packageDo.setWeight(sizeTemp[3] == 0 ? size[3] : sizeTemp[3]);
//                    LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
//                    wrapper.eq(DicBusinessItemDo::getDicBusinessId, 32L);
//                    List<Long> dicIds = dicBusinessItemDao.selectList(wrapper).stream()
//                            .map(DicBusinessItemDo::getId).collect(Collectors.toList());
//                    LambdaQueryWrapper<StorageServiceProjectDo> sspWrapper = new LambdaQueryWrapper<>();
//                    sspWrapper.in(StorageServiceProjectDo::getType, dicIds);
//                    List<StorageServiceProjectDo> storageServiceProjectDos = storageServiceProjectDao.selectList(sspWrapper);
//                    for (StorageServiceProjectDo storageServiceProjectDo : storageServiceProjectDos) {
//                        double sizeD = sizeTemp[0] + sizeTemp[1] + sizeTemp[2];
//                        if (sizeD < 150)
//                            if (storageServiceProjectDo.getCapacity() > sizeD) {
//                                packageDo.setConsumablesId(storageServiceProjectDo.getId());
//                                break;
//                            }
//                    }
//                    packageDoList.add(packageDo);
//                    size = new double[4];
//                    size = mShipPriceService.countSameSkuSize(size, productDo.getProductId(), 1);
//                    if (verifyMaxSize(size, companyId, storageId)) {
//                        size = new double[4];
//                    }
//                }
//            }
//        }
//        if (packageDoList.size() < 1 || !verifyMaxSize(size, companyId, storageId)) {
//            OrderOutputPackageDo packageDo = new OrderOutputPackageDo();
//            packageDo.setLength(size[0]);
//            packageDo.setWidth(size[1]);
//            packageDo.setHeight(size[2]);
//            packageDo.setWeight(size[3]);
//            packageDoList.add(packageDo);
//        }
//        return packageDoList;
//    }

    /**
     * 获取包裹捆包信息
     *
     * @param productDoList
     * @param size
     * @param storageId
     * @return
     */
    private List<OrderOutputPackageDetailDo> getPackageSizeInfoCount(List<OrderOutputProductDo> productDoList, double[] size, Long storageId) {
        size = new double[4];
        int totalCount = 0;
        int currentCount = 0;
        List<OrderOutputPackageDetailDo> packageDoList = new ArrayList<>();
        for (OrderOutputProductDo productDo : productDoList) {
            totalCount = totalCount + productDo.getCount();
        }
        double[] sizeTemp = new double[]{size[0], size[1], size[2], size[3]};
        double[] sizeLast = new double[4];
        int inCount = 0;
        StringBuilder skuId = new StringBuilder();
        for (int j = 0; j < productDoList.size(); j++) {
            OrderOutputProductDo productDo = productDoList.get(j);
            for (int i = 0; i < productDo.getCount(); i++) {
                boolean isMulti = false;
                ProductInfoDo productBean = productInfoDao.selectById(productDo.getProductId());
                double[] sizeP = mShipPriceService.getSizeOrderDesc(productBean.getWidth(), productBean.getHeight(), productBean.getLength());
                if ((sizeLast[0] != 0 && sizeLast[0] != sizeP[0]) || (sizeLast[1] != 0 && sizeLast[1] != sizeP[1])) {
                    //如果当前SKU和上一个SKU长宽 边不等，则不能捆包，返回true
                    isMulti = true;
                }
                if (i + j > 0 && verifyMaxSize(mShipPriceService.countSameSkuSizeNew(sizeTemp, productDo.getProductId(), 1), isMulti, storageId) || inNoPackageProductList(productDo.getProductId())) {
                    //新创建一个包裹
                    OrderOutputPackageDetailDo packageDo = new OrderOutputPackageDetailDo();
                    packageDo.setLength(sizeTemp[0]);
                    packageDo.setWidth(sizeTemp[1]);
                    packageDo.setHeight(sizeTemp[2]);
                    packageDo.setWeight(sizeTemp[3]);
                    packageDo.setInCount(inCount);
                    packageDo.setInSkuId(skuId.toString());
                    LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(DicBusinessItemDo::getDicBusinessId, 32L);
                    List<Long> dicIds = dicBusinessItemDao.selectList(wrapper).stream().map(DicBusinessItemDo::getId).collect(Collectors.toList());
                    LambdaQueryWrapper<StorageServiceProjectDo> sspWrapper = new LambdaQueryWrapper<>();
                    sspWrapper.in(StorageServiceProjectDo::getType, dicIds);
                    List<StorageServiceProjectDo> storageServiceProjectDos = storageServiceProjectDao.selectList(sspWrapper);
                    for (StorageServiceProjectDo storageServiceProjectDo : storageServiceProjectDos) {
                        double sizeD = sizeTemp[0] + sizeTemp[1] + sizeTemp[2];
                        if (sizeD < 150) if (storageServiceProjectDo.getCapacity() > sizeD) {
                            packageDo.setConsumablesId(storageServiceProjectDo.getId());
                            break;
                        }
                    }
                    packageDoList.add(packageDo);
                    size = new double[4];
                    size = mShipPriceService.countSameSkuSize(size, productDo.getProductId(), 1);
                    sizeTemp[0] = size[0];
                    sizeTemp[1] = size[1];
                    sizeTemp[2] = size[2];
                    sizeTemp[3] = size[3];
                    inCount = 1;
                    skuId = new StringBuilder();
                    skuId.append(productDo.getProductId() + ",");
                } else {
                    //跟上一个同一包裹
                    inCount++;
                    skuId.append(productDo.getProductId() + ",");
                    sizeTemp = mShipPriceService.countSameSkuSizeNew(sizeTemp, productDo.getProductId(), 1);
                }
                sizeLast = new double[]{sizeP[0], sizeP[1], sizeP[2], productBean.getWeight()};

                if (currentCount == totalCount - 1) {
                    OrderOutputPackageDetailDo packageDo = new OrderOutputPackageDetailDo();
                    packageDo.setLength(sizeTemp[0]);
                    packageDo.setWidth(sizeTemp[1]);
                    packageDo.setHeight(sizeTemp[2]);
                    packageDo.setWeight(sizeTemp[3]);
                    packageDo.setInCount(inCount);
                    packageDo.setInSkuId(skuId.toString());
                    packageDoList.add(packageDo);
                }
                currentCount++;
            }
        }
        return packageDoList;
    }

    /**
     * 不捆包产品清单
     *
     * @param productId
     * @return
     */
    private boolean inNoPackageProductList(Long productId) {
        if (productId == null) return true;
        List<Long> productList = getNoPackageProductList();
        long count = productList.stream().filter(aLong -> {
            return aLong.intValue() == productId.intValue();
        }).count();
        if (count > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public SingleResult updateOrderWaitSend(Map<String, String> map, List<Long> ids, Long currentUserId, HttpServletResponse response) {
        List<OrderOutputDo> orderOutputDoList;
        if (ids != null && ids.size() > 0) {
            orderOutputDoList = dao.selectList(new LambdaQueryWrapper<OrderOutputDo>().in(OrderOutputDo::getId, ids).and(i -> i.eq(OrderOutputDo::getStatus, DicBusinessItemConstant.outCreateCheckState).or().eq(OrderOutputDo::getStatus, DicBusinessItemConstant.outCreateState).or().eq(OrderOutputDo::getStatus, DicBusinessItemConstant.waitingPickUp).or().eq(OrderOutputDo::getStatus, DicBusinessItemConstant.alreadyPickUp)));
        } else {
            throw new BizException(SysConstant.Pls_Choose_Order);
        }
        for (OrderOutputDo orderOutputDo : orderOutputDoList) {
            //已审核 状态变成 已打单 不需要关联拣货单 , 待拣货状态 需要帮其 完成拣货，锁定库存， 已拣货状态 只需要更新状态
            StockPickUpDo pickUpDo = null;
            if (DicBusinessItemConstant.waitingPickUp.equals(orderOutputDo.getStatus()) && orderOutputDo.getPickUpId() != null) {
                //待拣货 且关联了pickId
                pickUpDo = stockPickUpDao.selectById(orderOutputDo.getPickUpId());
                if (pickUpDo == null) {
                    throw new BizException(SysConstant.OrderOutput_Pickup_NotMatch_OrderNo, orderOutputDo.getOrderOutputNumber());
                }
            }
            orderOutputDo.setStatus(DicBusinessItemConstant.outWaitSendOut);
            orderOutputDo.setUpdateTime(new Date());
            orderOutputDo.setUpdateBy(currentUserId);
            dao.updateById(orderOutputDo);

            if (pickUpDo != null) {
                stockPickUpService.finishPickUpAfter(pickUpDo, currentUserId);
            }
        }
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                for (OrderOutputDo et : orderOutputDoList) {
                    operateRecordDao.operateAddRecord(SysConstant.OPERATE_PRINT_ORDER, et.getId(), currentUserId, 3);
//                    operateRecord("打单", et.getId(), currentUserId);
                }
            }
        });
        return SingleResult.success();
    }

    @Override
    public SingleResult exportTrackExpress(Map<String, String> map, List<Long> ids, Long currentUserId, HttpServletResponse response) throws IOException {
//        QueryWrapper<OrderOutputDo> wrapper = queryBuild(map);
        List<OrderOutputDo> orderOutputDoList;
        if (ids != null && ids.size() > 0) {
            orderOutputDoList = this.baseMapper.selectBatchIds(ids);
        } else {
//            response.setStatus(500);
//            return null;
//            orderOutputDoList = this.baseMapper.selectList1(map);
            throw new BizException(SysConstant.Pls_Choose_Order);
        }

        List<OrderOutputCommonExportVo> excelExportVoList = new ArrayList<>();
        List<OrderOutputYamatoExportVo> yamatoExportVoList = new ArrayList<>();
        List<OrderOutputSagawaExportVo> sagawaExportVoList = new ArrayList<>();
        List<OrderOutputSagawaExportNewVo> sagawaNewExportVoList = new ArrayList<>();
        List<OrderOutputSeinoExportVo> seinoExportVoList = new ArrayList<>();
        List<OrderOutputJpCommonExportVo> jpCommonExportVoList = new ArrayList<>();
        List<OrderOutputJpCodExportVo> jpCodExportVoList = new ArrayList<>();
        List<OrderOutputJpPackageExportVo> jpPackageExportVoList = new ArrayList<>();
        StorageDo storageDo = storageDao.selectById(map.get("storageId"));
        String storageName = storageDo == null ? "" : storageDo.getStorageName();
        DicBusinessItemDo itemDo = dicBusinessItemDao.selectById(map.get("trackId"));
        switch (map.get("trackId")) {
            case "8"://佐川
                CsvExportParams exportParams = new CsvExportParams();
                exportParams.setCreateHeadRows(true);
                exportParams.setEncoding("Shift-JIS");
                if ("12".equals(map.get("storageId"))) {
                    orderOutputDoList.forEach(orderOutputDo -> {
                        QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
                        wrapper1.eq("order_output_id", orderOutputDo.getId());
                        List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
                        dealwithPrintLabelPackageInfo(packageList, orderOutputDo, storageDo, currentUserId);
                        if (packageList != null && packageList.size() > 0) {
                            packageList.forEach(orderInputProductDo -> {
                                sagawaNewExportVoList.add(buidSagawaNewExportData(orderOutputDo, orderInputProductDo));
                            });
                        }
                    });

                    //排序
                    sagawaNewExportVoList.sort(new Comparator<OrderOutputSagawaExportNewVo>() {
                        @Override
                        public int compare(OrderOutputSagawaExportNewVo o1, OrderOutputSagawaExportNewVo o2) {
                            return trackExpressSort(map.get("storageId"), o1.getCommoditySku(), o2.getCommoditySku(), o1, o2);
                        }
                    });
                    CsvUtils.exportCsv(exportParams, OrderOutputSagawaExportNewVo.class, sagawaNewExportVoList, TimeUtils.getCurrentDateFormat("M-d") + storageName + (itemDo != null ? itemDo.getDicItemValue() : "Sagawa") + "出荷依頼V3.csv", response);
//                        ExcelUtils.exportExcel(sagawaExportVoList, OrderOutputSagawaExportVo.class, TimeUtils.getCurrentDateFormat() + "Sagawa出荷依頼.xls", new ExportParams(), response);
                    break;
                } else {
                    orderOutputDoList.forEach(orderOutputDo -> {
                        QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
                        wrapper1.eq("order_output_id", orderOutputDo.getId());
                        List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
                        dealwithPrintLabelPackageInfo(packageList, orderOutputDo, storageDo, currentUserId);
                        if (packageList != null && packageList.size() > 0) {
                            packageList.forEach(orderInputProductDo -> {
                                sagawaExportVoList.add(buidSagawaExportData(orderOutputDo, orderInputProductDo));
                            });
                        }
                    });

                    //排序
                    sagawaExportVoList.sort(new Comparator<OrderOutputSagawaExportVo>() {
                        @Override
                        public int compare(OrderOutputSagawaExportVo o1, OrderOutputSagawaExportVo o2) {
                            return trackExpressSort(map.get("storageId"), o1.getCommoditySku(), o2.getCommoditySku(), o1, o2);
                        }
                    });

                    CsvUtils.exportCsv(exportParams, OrderOutputSagawaExportVo.class, sagawaExportVoList, TimeUtils.getCurrentDateFormat("M-d") + storageName + (itemDo != null ? itemDo.getDicItemValue() : "Sagawa") + "出荷依頼.csv", response);
//                        ExcelUtils.exportExcel(sagawaExportVoList, OrderOutputSagawaExportVo.class, TimeUtils.getCurrentDateFormat() + "Sagawa出荷依頼.xls", new ExportParams(), response);
                }
                break;
            case "9"://黑猫
            case "162"://黑猫
            case "163":
            case "179":
                orderOutputDoList.forEach(orderOutputDo -> {
                    QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("order_output_id", orderOutputDo.getId());
                    List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
                    dealwithPrintLabelPackageInfo(packageList, orderOutputDo, storageDo, currentUserId);
                    if (packageList != null && packageList.size() > 0) packageList.forEach(orderInputProductDo -> {
                        yamatoExportVoList.add(buildYamatoExportData(orderOutputDo, orderInputProductDo));
                    });
                });
                //排序
                yamatoExportVoList.sort(new Comparator<OrderOutputYamatoExportVo>() {
                    @Override
                    public int compare(OrderOutputYamatoExportVo o1, OrderOutputYamatoExportVo o2) {
                        return trackExpressSort(map.get("storageId"), o1.getCommoditySku(), o2.getCommoditySku(), o1, o2);
                    }
                });
                ExcelUtils.exportExcel(yamatoExportVoList, OrderOutputYamatoExportVo.class, TimeUtils.getCurrentDateFormat("M-d") + storageName + (itemDo != null ? itemDo.getDicItemValue() : "YAMATO") + "出荷依頼.xls", new ExportParams(), response);
                break;
            case "10"://邮政
                orderOutputDoList.stream().forEach(orderOutputDo -> {
                    QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("order_output_id", orderOutputDo.getId());
                    List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
                    dealwithPrintLabelPackageInfo(packageList, orderOutputDo, storageDo, currentUserId);
                    if (packageList != null && packageList.size() > 0) packageList.forEach(orderInputProductDo -> {
                        jpPackageExportVoList.add(buildJpostPackageExportData(orderOutputDo, orderInputProductDo));
                    });
                });
                //排序
                jpPackageExportVoList.sort(new Comparator<OrderOutputJpPackageExportVo>() {
                    @Override
                    public int compare(OrderOutputJpPackageExportVo o1, OrderOutputJpPackageExportVo o2) {
                        return trackExpressSort(map.get("storageId"), o1.getOrderNo(), o2.getOrderNo(), o1, o2);
                    }
                });
                exportParams = new CsvExportParams();
                exportParams.setCreateHeadRows(false);
                exportParams.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams, OrderOutputJpPackageExportVo.class, jpPackageExportVoList, TimeUtils.getCurrentDateFormat("M-d") + storageName + (itemDo != null ? itemDo.getDicItemValue() : "Jpost") + "出荷依頼.csv", response);
//                        ExcelUtils.exportExcel(jpPackageExportVoList, OrderOutputJpPackageExportVo.class, TimeUtils.getCurrentDateFormat() + "Jpost出荷依頼.xls", exportParams, response);
                break;
            case "42":
                orderOutputDoList.forEach(orderOutputDo -> {
                    QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("order_output_id", orderOutputDo.getId());
                    List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
                    dealwithPrintLabelPackageInfo(packageList, orderOutputDo, storageDo, currentUserId);
                    for (OrderOutputPackageDo orderOutputPackageDo : packageList) {
                        seinoExportVoList.add(buildSeinoExportData(orderOutputDo, orderOutputPackageDo));
                    }
                });
                //排序
                seinoExportVoList.sort(new Comparator<OrderOutputSeinoExportVo>() {
                    @Override
                    public int compare(OrderOutputSeinoExportVo o1, OrderOutputSeinoExportVo o2) {
                        return trackExpressSort(map.get("storageId"), o1.getCommoditySku1(), o2.getCommoditySku1(), o1, o2);

                    }
                });
                CsvExportParams exportParamsX = new CsvExportParams();
                exportParamsX.setCreateHeadRows(false);
                exportParamsX.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParamsX, OrderOutputSeinoExportVo.class, seinoExportVoList, TimeUtils.getCurrentDateFormat("M-d") + storageName + (itemDo != null ? itemDo.getDicItemValue() : "Seino") + "出荷依頼.csv", response);
                break;
            case "44":
                orderOutputDoList.forEach(orderOutputDo -> {
                    QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("order_output_id", orderOutputDo.getId());
                    List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
                    for (OrderOutputPackageDo orderOutputPackageDo : packageList) {
                        jpCommonExportVoList.add((OrderOutputJpCommonExportVo) buidJPost2ExportData(orderOutputDo, orderOutputPackageDo));
                    }
                });
                //排序
                jpCommonExportVoList.sort(new Comparator<OrderOutputJpCommonExportVo>() {
                    @Override
                    public int compare(OrderOutputJpCommonExportVo o1, OrderOutputJpCommonExportVo o2) {
                        return trackExpressSort(map.get("storageId"), o1.getCommoditySku(), o2.getCommoditySku(), o1, o2);

                    }
                });
                try {
                    ExcelUtils.exportExcel(jpCommonExportVoList, OrderOutputJpCommonExportVo.class, TimeUtils.getCurrentDateFormat() + "出荷依頼.xls", new ExportParams(), response);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case "79":
                orderOutputDoList.forEach(orderOutputDo -> {
                    QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("order_output_id", orderOutputDo.getId());
                    List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
                    for (OrderOutputPackageDo orderOutputPackageDo : packageList) {
                        jpCodExportVoList.add((OrderOutputJpCodExportVo) buidJPostCodExportData(orderOutputDo, orderOutputPackageDo));
                    }
                });
                //排序
                jpCodExportVoList.sort(new Comparator<OrderOutputJpCodExportVo>() {
                    @Override
                    public int compare(OrderOutputJpCodExportVo o1, OrderOutputJpCodExportVo o2) {
                        return trackExpressSort(map.get("storageId"), o1.getCommoditySku(), o2.getCommoditySku(), o1, o2);

                    }
                });
                try {
                    ExcelUtils.exportExcel(jpCodExportVoList, OrderOutputJpCodExportVo.class, TimeUtils.getCurrentDateFormat() + "出荷依頼.xls", new ExportParams(), response);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            default:
                orderOutputDoList.stream().sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null) {
                            if (o2.getCommoditySku() == null) {
                                return 0;
                            }
                            return 1;
                        } else if (o2.getCommoditySku() == null) {
                            return -1;
                        }
                        return o1.getCommoditySku().compareToIgnoreCase(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper<OrderOutputProductDo> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    productDoList.forEach(orderOutputProductDo -> {
                        OrderOutputCommonExportVo exportVo = new OrderOutputCommonExportVo();
                        ProductInfoDo productInfoDo = productInfoDao.selectById(orderOutputProductDo.getProductId());
                        exportVo.setAddress(orderOutputDo.getAddress());
                        if (productInfoDo != null) {
                            exportVo.setProductName(productInfoDo.getProductName());
                            exportVo.setCommoditySku(productInfoDo.getCommoditySku());
                        }
                        exportVo.setCount(orderOutputProductDo.getCount());
                        if (orderOutputDo.getDeliveryDate() != null)
                            exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate(), "yyyy/MM/dd"));
                        exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
                        exportVo.setOrderName(orderOutputDo.getReceiverName());
                        exportVo.setPostCode(orderOutputDo.getPostCode());
                        exportVo.setAddress(orderOutputDo.getAddress());
                        exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber());
                        exportVo.setTelPhone(orderOutputDo.getTelPhone());
                        excelExportVoList.add(exportVo);
                    });
                });
                ExcelUtils.exportExcel(excelExportVoList, OrderOutputCommonExportVo.class, TimeUtils.getCurrentDateFormat() + "出荷依頼.xls", new ExportParams(), response);
                //exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response)
                break;
        }
//        updateOrderCheckStatus(ids, DicBusinessItemConstant.outCreateCheckState, currentUserId);
//        orderOutputDoList = orderOutputDoList.stream()
//                .filter(orderOutputDo -> orderOutputDo.getStatus() == DicBusinessItemConstant.outCreateCheckState ||
//                        orderOutputDo.getStatus() == DicBusinessItemConstant.outCreateState)
//                .map(orderOutputDo -> {
//                    orderOutputDo.setStatus(DicBusinessItemConstant.outWaitSendOut);
//                    orderOutputDo.setUpdateTime(new Date());
//                    return orderOutputDo;
//                }).collect(Collectors.toList());
//        if (orderOutputDoList.size() < 1)
//            return  SingleResult.success();
//        boolean b = updateBatchById(orderOutputDoList);
//        return b ? SingleResult.success() : SingleResult.failure("更新失败，请联系管理员");
        return null;
    }

    private void dealwithPrintLabelPackageInfo(List<OrderOutputPackageDo> packageList, OrderOutputDo orderOutputDo, StorageDo storageDo, Long currentUserId) {
        QueryWrapper<OrderOutputProductDo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", orderOutputDo.getId());
        List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper);
        double[] size = mShipPriceService.getMulitSkuSize(productDoList);
        splitPackageInfo(packageList, productDoList, orderOutputDo.getId(), orderOutputDo.getCompanyId(), orderOutputDo.getStorageId(), storageDo.getSupportShip(), size, currentUserId);
    }

    /**
     * 把包裹拆分发货
     *
     * @param packageDoList
     * @param productDoList
     * @param id
     * @param companyId
     * @param storageId
     * @param supportShip
     * @param size
     * @param updateBy
     */
    private void splitPackageInfo(List<OrderOutputPackageDo> packageDoList, List<OrderOutputProductDo> productDoList, Long id, Long companyId, Long storageId, String supportShip, double[] size, Long updateBy) {
        //捆包完多个个包裹
        List<OrderOutputPackageDetailDo> packageDoListCount = getPackageSizeInfoCount(productDoList, size, storageId);
        LambdaQueryWrapper<OrderOutputPackageDetailDo> lambdaDeleteWrapper = new LambdaQueryWrapper<>();
        lambdaDeleteWrapper.eq(OrderOutputPackageDetailDo::getPackageId, packageDoList.get(0).getId());
        lambdaDeleteWrapper.eq(OrderOutputPackageDetailDo::getOrderOutputId, id);
        packageDetailDao.delete(lambdaDeleteWrapper);
        if ("1".equals(supportShip)) {
            for (OrderOutputPackageDetailDo packageDo : packageDoListCount) {
                //保存 捆包分包详情表
                OrderOutputPackageDetailDo detailDo = packageDo;
                detailDo.setPackageId(packageDoList.get(0).getId());
                detailDo.setOrderOutputId(id);
                detailDo.setCount(1);
                detailDo.setCreateBy(updateBy);
                detailDo.setCreateTime(new Date());
                packageDetailDao.insert(detailDo);
            }
        } else {
//            for (OrderOutputProductDo packageDo : productDoList) {
//                //保存 捆包分包详情表
//                OrderOutputPackageDetailDo detailDo = new OrderOutputPackageDetailDo();
//                detailDo.setPackageId(packageDoList.get(0).getId());
//                detailDo.setOrderOutputId(id);
//                detailDo.setCount(1);
//                detailDo.setCreateBy(updateBy);
//                detailDo.setCreateTime(new Date());
//                packageDetailDao.insert(detailDo);
//            }
        }
    }


    private int trackExpressSort(String storageId, String sku1, String sku2, OrderOutputExportSortVo o1, OrderOutputExportSortVo o2) {
        if ("10".equals(storageId)) {
            if (o1.getOrderType() < o2.getOrderType()) {
                return -1;
            } else if (o1.getOrderType() > o2.getOrderType()) {
                return 1;
            } else if (o1.getOrderType() == o2.getOrderType() && o1.getOrderType() == 1) {
                //一单多件的情况 此前取了体积最大sku对应库位 的顺序
                return this.sortByRack(sku1, sku2, o1, o2);
            } else {
                if (o1.getRackCount() < o2.getRackCount()) {
                    return -1;
                } else if (o1.getRackCount() > o2.getRackCount()) {
                    return 1;
                } else {
                    return this.sortByRack(sku1, sku2, o1, o2);
                }
            }
        } else {
            if (sku1 == null) {
                if (sku2 == null) {
                    return 0;
                }
                return 1;
            } else if (sku2 == null) {
                return -1;
            }
            return sku1.compareToIgnoreCase(sku2);
        }
    }

    public int sortByRack(String sku1, String sku2, OrderOutputExportSortVo o1, OrderOutputExportSortVo o2) {
        //一单一个sku，但是数量多个，牵扯到多个库位
        //先判断 货架拣货顺序
        if (o1.getShelfSort() == null) {
            if (o2.getShelfSort() == null) {
                //当都是默认库位时，也要按照sku排序
                return sku1.compareToIgnoreCase(sku2);
            }
            return 1;
        } else if (o2.getShelfSort() == null) {
            if (o1.getShelfSort() == null) {
                //当都是默认库位时，也要按照sku排序
                return sku1.compareToIgnoreCase(sku2);
            }
            return -1;
        } else {
            if (o1.getShelfSort().compareTo(o2.getShelfSort()) < 0) {
                return -1;
            } else if (o1.getShelfSort().compareTo(o2.getShelfSort()) > 0) {
                return 1;
            } else {
                if (o1.getRackSort() == null) {
                    if (o2.getRackSort() == null) return sku1.compareToIgnoreCase(sku2);
                    return 1;
                } else if (o2.getRackSort() == null) {
                    return -1;
//                        } else if (o1.getRackSort().equals(o2.getRackSort())){
//
                } else {
                    //当库位是同一个时，在按照SKU排序
                    return o1.getRackSort().compareTo(o2.getRackSort()) == 0 ? sku1.compareToIgnoreCase(sku2) : o1.getRackSort().compareTo(o2.getRackSort());
                }
            }
        }
    }

    public void sortByVolume(List<OrderOutputProductSortRes> sortResList) {
        //将sortResList 按 体积排序
        sortResList.sort(new Comparator<OrderOutputProductSortRes>() {
            @Override
            public int compare(OrderOutputProductSortRes o1, OrderOutputProductSortRes o2) {
                if (o1.getVolume() - o2.getVolume() < 0) {
                    return 1;
                } else if (o1.getVolume() - o2.getVolume() > 0) {
                    return -1;
                } else {
                    return o1.getCommoditySku().compareToIgnoreCase(o2.getCommoditySku());
                }
            }
        });
    }

    private OrderOutputSeinoExportVo buildSeinoExportData(OrderOutputDo orderOutputDo, OrderOutputPackageDo packageDo) {
        OrderOutputSeinoExportVo exportVo = new OrderOutputSeinoExportVo();
//        exportVo.setSendDate(TimeUtils.formatDate(orderOutputDo.getSendDate(), "yyy/MM/dd"));
        if (orderOutputDo.getCompanyId() == 75) {
            exportVo.setManagerNo("04713618303");
            exportVo.setBaoxian("5");
        }
        exportVo.setOrderId("OT" + orderOutputDo.getId());
        exportVo.setPhone(orderOutputDo.getTelPhone());
        if (StringUtils.isNotBlank(orderOutputDo.getReceiverName())) {
            if (orderOutputDo.getReceiverName().length() > 30) {
                exportVo.setName1(orderOutputDo.getReceiverName().substring(0, 30));
                exportVo.setName2(orderOutputDo.getReceiverName().substring(30));
            } else {
                exportVo.setName1(orderOutputDo.getReceiverName());
            }
        }
        exportVo.setPostcode(orderOutputDo.getPostCode().replaceAll("-", "").replaceAll("－", ""));
        if ((orderOutputDo.getArea() != null && orderOutputDo.getAddress().contains(orderOutputDo.getArea()))) {
            orderOutputDo.getAddress().trim().replaceAll(orderOutputDo.getArea(), "").replaceAll("-", "-").replaceAll("－", "-");
        }
        if (orderOutputDo.getAddress().length() <= 30) {
            exportVo.setAddress1(orderOutputDo.getAddress());
        } else {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 30));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(30));
        }
        exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());

        int count = 0;
        double packageWeight = 0;
        //此时有对应库位情况，一队多 按商品体积排序
        List<OrderOutputProductRackDto> productDoList = productDao.getProductRackDto(packageDo.getId());
        Map<Long, List<OrderOutputProductRackDto>> listMap = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductRackDto::getId));
        StringBuilder sku = new StringBuilder();
        StringBuilder storageSku = new StringBuilder();
        if (listMap.keySet().size() > 1) {
            //yidan duojian
            exportVo.setOrderType(1);
        }
        exportVo.setRackSort(productDoList.get(0).getRackSort());
        exportVo.setShelfSort(productDoList.get(0).getShelfSort());

        Set<Long> rackIdSet = new HashSet<>();

        Map<String, Integer> rackProductCountMap = new HashMap<>();
        List<OrderOutputProductSortRes> sortResList = new ArrayList<>();
        int i = 0;
        for (Long id : listMap.keySet()) {
            List<OrderOutputProductRackDto> rackDtoList = listMap.get(id);
            OrderOutputProductRackDto productDo = rackDtoList.get(0);
            count = count + productDo.getCount();
            packageWeight += productDo.getWeight() * productDo.getCount();
//            if (storageSku.length() > 0) {
//                storageSku.append(" ");
//            }
//            if (sku.length() > 0) {
//                sku.append(" ");
//            }
//            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
//            sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
            sortResList.add(new OrderOutputProductSortRes(productDo.getStorageSku(), productDo.getCommoditySku(), productDo.getCommodityName(), productDo.getCount(), productDo.getVolume()));
            for (OrderOutputProductRackDto rackDto : rackDtoList) {
                if (rackDto.getPickNumber() == null) {
                    continue;
                }
                rackIdSet.add(rackDto.getRackId());
                rackProductCountMap.merge(rackDto.getRackId() + "_" + (StringUtils.isBlank(rackDto.getPositionName()) ? "M" : rackDto.getPositionName()), rackDto.getPickNumber(), Integer::sum);
            }
            if (i == 0) {
                exportVo.setCommoditySku1("【" + productDo.getCommoditySku() + "*" + productDo.getCount() + "】");
                exportVo.setStorageSku1(productDo.getStorageSku() + "*" + productDo.getCount());
//            } else {
//                exportVo.setCommoditySku2("【" + productDo.getCommoditySku() + "*" + productDo.getCount() + "】");
//                exportVo.setStorageSku2(productDo.getStorageSku() + "*" + productDo.getCount());
            }
            i++;
        }

        //将sortResList 按 体积排序
        this.sortByVolume(sortResList);
        for (OrderOutputProductSortRes productDo : sortResList) {
            if (storageSku.length() > 0) {
                storageSku.append(" ");
            }
            if (sku.length() > 0) {
                sku.append(" ");
            }
            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
            sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
        }
        exportVo.setRackCount(rackProductCountMap.size());
        exportVo.setRackCount(rackIdSet.size());

        if (listMap.keySet().size() > 1) {
            exportVo.setCommoditySku1("【" + sku.toString() + "】");
            exportVo.setStorageSku1(storageSku.toString());
        }
        //库位
        String position = this.getPosition(rackProductCountMap);
        exportVo.setCommoditySku2(position);

        String date = "0000";
        if (orderOutputDo.getDeliveryDate() != null || orderOutputDo.getDeliveryTime() != null) {
            if (orderOutputDo.getDeliveryDate() != null) {
                if (orderOutputDo.getDeliveryDate().getTime() < System.currentTimeMillis()) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.add(Calendar.DAY_OF_YEAR, 1);
                    date = TimeUtils.formatDate(calendar.getTime(), "MMdd");
                } else {
                    date = TimeUtils.formatDate(orderOutputDo.getDeliveryDate(), "MMdd");
                }
            }
            String timeCode = "0";
            if (orderOutputDo.getDeliveryTime() != null) {
                timeCode = TimeUtils.getXinongDTime(orderOutputDo.getDeliveryTime());
            }
            date = date + timeCode;
            if (!date.equals("00000")) {
                exportVo.setDeliveryTime(date);
                exportVo.setE39("02");
            }
        }
        exportVo.setCount(count);
        if (packageWeight > 0) {
            exportVo.setWeight(new BigDecimal(packageWeight).setScale(0, RoundingMode.UP).toPlainString());
        } else {
            exportVo.setWeight("5");
        }
        return exportVo;

    }


    private OrderOutputTHKExportVO buidThkExportData(OrderOutputDo orderOutputDo, OrderOutputProductDo orderOutputProductDo) {

        OrderOutputTHKExportVO exportVo = new OrderOutputTHKExportVO();
        ProductInfoDo productInfoDo = productInfoDao.selectById(orderOutputProductDo.getProductId());
        exportVo.setAddress((orderOutputDo.getArea() == null ? "" : orderOutputDo.getArea()) + orderOutputDo.getAddress());
        if (productInfoDo != null) {
            exportVo.setProductName(productInfoDo.getCommodityName());
            exportVo.setCommoditySku(productInfoDo.getCommoditySku());
        }
        exportVo.setCount(orderOutputProductDo.getCount());
        if (orderOutputDo.getDeliveryDate() != null) {
            exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate(), "yyyyMMdd"));
        } else {
            exportVo.setDeliveryDate(TimeUtils.getCurrentDateFormat(2).replaceAll("-", ""));
        }
        if (orderOutputDo.getDeliveryTime() != null) exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
        exportVo.setOrderName(orderOutputDo.getReceiverName());
        if (orderOutputDo.getSendDate() != null)
            exportVo.setSendDate(TimeUtils.formatDate(orderOutputDo.getSendDate()));
        exportVo.setTips(orderOutputDo.getTips());
        exportVo.setTrackNumber(orderOutputDo.getTrackNumber());
        exportVo.setPostCode(orderOutputDo.getPostCode());
        exportVo.setAddress(orderOutputDo.getAddress().replaceAll("-", "-").replaceAll("－", "-"));
        exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber());
        exportVo.setTelPhone(orderOutputDo.getTelPhone());
        return exportVo;
    }

    private OrderOutputKSWExportVo buidKswExportData(OrderOutputDo orderOutputDo, OrderOutputProductDo orderInputProductDo) {
        OrderOutputKSWExportVo exportVo = new OrderOutputKSWExportVo();
        ProductInfoDo productInfoDo = productInfoDao.selectById(orderInputProductDo.getProductId());
        exportVo.setAddress((orderOutputDo.getArea() == null ? "" : orderOutputDo.getArea()) + orderOutputDo.getAddress());
        if (productInfoDo != null) {
            exportVo.setProductName(productInfoDo.getCommodityName());
            exportVo.setCommoditySku(productInfoDo.getCommoditySku());
        }
        exportVo.setCount(orderInputProductDo.getCount());
        if (orderOutputDo.getDeliveryDate() != null) {
            exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate(), "yyyyMMdd"));
        } else {
            exportVo.setDeliveryDate(TimeUtils.getCurrentDateFormat(2).replaceAll("-", ""));
        }
        if (orderOutputDo.getDeliveryDate() != null) {
            exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
        } else {
            exportVo.setDeliveryTime("1");
        }
        exportVo.setOrderName(orderOutputDo.getReceiverName());
        exportVo.setPostCode(orderOutputDo.getPostCode());
        exportVo.setAddress(orderOutputDo.getAddress());
        exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber());
        exportVo.setTelPhone(orderOutputDo.getTelPhone());
        exportVo.setTips(orderOutputDo.getTips());
        exportVo.setTrackNumber(orderOutputDo.getTrackNumber());
        return exportVo;
    }

    private OrderOutputSKLExportVo buidSKLExportData(OrderOutputDo orderOutputDo, OrderOutputProductDo productDo) {
        OrderOutputSKLExportVo exportVo = new OrderOutputSKLExportVo();
        exportVo.setSendDate(TimeUtils.formatDate(orderOutputDo.getSendDate()));
        exportVo.setPostCode(orderOutputDo.getPostCode());
        exportVo.setTelPhone(orderOutputDo.getTelPhone());
        exportVo.setAddress((orderOutputDo.getArea() == null ? "" : orderOutputDo.getArea()) + orderOutputDo.getAddress());
        exportVo.setOrderName(orderOutputDo.getReceiverName());
        ProductInfoDo infoDo = productInfoDao.selectById(productDo.getProductId());
        if (infoDo != null) {
            exportVo.setCommoditySku(infoDo.getCommoditySku());
            exportVo.setProductName(infoDo.getCommodityName());
            exportVo.setCount(String.valueOf(productDo.getCount()));
        }
        exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber());
        if (orderOutputDo.getDeliveryDate() != null) {
            exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate()));
        }
//        exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
        if (StringUtils.isNotBlank(orderOutputDo.getDeliveryTime())) {
            if ("-".equals(orderOutputDo.getDeliveryTime())) {
                exportVo.setDeliveryTime("");
            } else {
                try {
                    int first = Integer.parseInt(orderOutputDo.getDeliveryTime().split("-")[0]);
                    int last = Integer.parseInt(orderOutputDo.getDeliveryTime().split("-")[1]);
                    if (last <= 12) {
                        exportVo.setDeliveryTime("08-12");
                    } else {
                        exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
                }
            }
        }
        if (orderOutputDo.getTrackId() == DicBusinessItemConstant.xinongExpress) {
            exportVo.setTips("西濃運輸 " + orderOutputDo.getTips());
        } else {
            exportVo.setTips(orderOutputDo.getTips());
        }
        exportVo.setTrackNumber(orderOutputDo.getTrackNumber());
        return exportVo;
    }


    public String getPosition(Map<String, Integer> rackProductCountMap) {
        StringBuilder position = new StringBuilder();
        for (String rack : rackProductCountMap.keySet()) {
            //默认库位排在后面
            if (rack.split("_")[1].equals("M")) {
                if (position.length() > 0) {
                    position.append(" ");
                }
                position.append(rack.split("_")[1]).append("*").append(rackProductCountMap.get(rack));
            } else {
                if (position.length() > 0) {
                    position.insert(0, " ");
                }
                position.insert(0, rackProductCountMap.get(rack));
                position.insert(0, "*");
                position.insert(0, rack.split("_")[1]);
            }
        }
        return position.toString();
    }

    private OrderOutputSagawaExportNewVo buidSagawaNewExportData(OrderOutputDo orderOutputDo, OrderOutputPackageDo orderInputProductDo) {
        OrderOutputSagawaExportNewVo exportVo = new OrderOutputSagawaExportNewVo();
        if (orderOutputDo.getStorageId() == 10 || orderOutputDo.getStorageId() == 11 || orderOutputDo.getStorageId() == 1) {
            exportVo.setE3("146671890039");
            exportVo.setE5("0471-36-1830");
            exportVo.setE6("0471-36-1830");
            exportVo.setE7("278-0002");
            exportVo.setE8("千葉県野田市木野崎字");
            exportVo.setE9("鹿野1788番地２-1");
            if (orderOutputDo.getCompanyId().intValue() == 221) {
                exportVo.setE10("RENOGY JAPAN株式会社");
            }
        } else if (orderOutputDo.getStorageId() == 12) {
            exportVo.setE3("");
            exportVo.setE5("0471361830");
            exportVo.setE6("0471361830");
            exportVo.setE7("5960015");
            exportVo.setE8("大阪府岸和田市");
            exportVo.setE9("地蔵浜11-2");
            exportVo.setE10("EC通販物流センター（関西）");
        }
        if (orderOutputDo.getShopId().intValue() == 1) {
            exportVo.setE10("MWPO（モロ）株式会社(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 2) {
            exportVo.setE10("SCM株式会社(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 3) {
            exportVo.setE10("チチロバ（TITIROBA）楽天市場店");
        } else if (orderOutputDo.getShopId().intValue() == 4) {
            exportVo.setE10("MWPO（モロ）株式会社(楽天)");
        } else if (orderOutputDo.getShopId().intValue() == 6) {
            exportVo.setE10("MWPO（モロ）株式会社公式サイト");
        } else if (orderOutputDo.getShopId().intValue() == 33) {
            exportVo.setE10("EOWO直営店(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 221) {
            exportVo.setE10("lifesia (AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 304) {
            exportVo.setE10("楽天titilife");
        } else if (orderOutputDo.getCompanyId().intValue() == 201) {
            exportVo.setE10("AfterShokz Official Store");
        } else if (orderOutputDo.getCompanyId() == 80) {
            exportVo.setE10("NIXGIRE LIMITED");
        } else if (orderOutputDo.getCompanyId().intValue() == 323) {
            exportVo.setE10("MamimamiHome");
        } else if (orderOutputDo.getCompanyId().intValue() == 263) {
            exportVo.setE10("UWANT");
        } else if (orderOutputDo.getCompanyId().intValue() == 218) {
            exportVo.setE10("CXWXC");
        } else if (orderOutputDo.getCompanyId().intValue() == 300) {
            exportVo.setE10("Morus(乾燥機)");
            exportVo.setE6("050-5534-9451");
        } else if (orderOutputDo.getCompanyId().intValue() == 221) {
            exportVo.setE10("RENOGY JAPAN株式会社");
            exportVo.setE6("048-299-9264");
            exportVo.setE7("3330866");
            exportVo.setE8("埼玉県川口市芝1丁目");
            exportVo.setE9("30-61F 柳ビル");
        } else if (orderOutputDo.getCompanyId() == 14) {
            exportVo.setE10("OneTigris Camping");
            exportVo.setE7("1580094");
            exportVo.setE8("東京都世田谷区玉川");
            exportVo.setE9("１-１４-１");
        } else if (orderOutputDo.getShopId().intValue() == 395) {
            exportVo.setE10("楽天市場 Greatstar Official");
            exportVo.setE6("0471-36-1830");
        }
        if (StringUtils.isNotBlank(orderOutputDo.getTelPhone())) {
            exportVo.setTelPhone(orderOutputDo.getTelPhone().replaceAll("\\n", "").replaceAll("\\+81", ""));
            if (exportVo.getTelPhone().startsWith("81")) {
                exportVo.setTelPhone(exportVo.getTelPhone().replaceFirst("81", ""));
            }
        }
        exportVo.setPostCode(orderOutputDo.getPostCode().replaceAll("-", "").replaceAll("\\n", ""));
        if (orderOutputDo.getArea() != null) {
            String area = StringsUtil.getJpAreaByEnglishCode(orderOutputDo.getArea());
            orderOutputDo.setAddress((orderOutputDo.getAddress().contains(area) ? "" : area) + orderOutputDo.getAddress().trim().replaceAll("\\n", "").replaceAll("\\t", " ").replaceAll("-", "-").replaceAll("－", "-"));
        } else {
            orderOutputDo.setAddress(orderOutputDo.getAddress().trim().replaceAll("\\n", "").replaceAll("\\t", " ").replaceAll("−", "-").replaceAll("－", "-"));
        }
        if (orderOutputDo.getAddress().length() <= 15) {
            exportVo.setAddress1(orderOutputDo.getAddress());
        } else if (orderOutputDo.getAddress().length() > 15 && orderOutputDo.getAddress().length() <= 30) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 15));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(15));
        } else {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 15));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(15, 30));
            exportVo.setAddress3(orderOutputDo.getAddress().substring(30));
        }
        if (StringUtils.isNotBlank(orderOutputDo.getReceiverName())) {
            orderOutputDo.setReceiverName(orderOutputDo.getReceiverName().replaceAll("\\n", ""));
            if (orderOutputDo.getReceiverName().length() <= 15) {
                exportVo.setReceiverName(orderOutputDo.getReceiverName());
            } else {
                exportVo.setReceiverName(orderOutputDo.getReceiverName().substring(0, 15));
                exportVo.setReceiverName2(orderOutputDo.getReceiverName().substring(15));
            }
        }
//        QueryWrapper<OrderOutputProductDo> wrapper = new QueryWrapper<>();
//        wrapper.eq("package_id", orderInputProductDo.getId());
        int count = 0;
        //此时有对应库位情况，一队多
        List<OrderOutputProductRackDto> productDoList = productDao.getProductRackDto(orderInputProductDo.getId());
        Map<Long, List<OrderOutputProductRackDto>> listMap = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductRackDto::getId));
        StringBuilder sku = new StringBuilder();
        StringBuilder storageSku = new StringBuilder();
        if (listMap.keySet().size() > 1) {
            //yidan duojian
            exportVo.setOrderType(1);
        }
        exportVo.setRackSort(productDoList.get(0).getRackSort());
        exportVo.setShelfSort(productDoList.get(0).getShelfSort());
        Set<Long> rackIdSet = new HashSet<>();

        Map<String, Integer> rackProductCountMap = new HashMap<>();

        List<OrderOutputProductSortRes> sortResList = new ArrayList<>();
        for (Long id : listMap.keySet()) {
            List<OrderOutputProductRackDto> rackDtoList = listMap.get(id);
            OrderOutputProductRackDto productDo = rackDtoList.get(0);
            count = count + productDo.getCount();
//            if (storageSku.length() > 0) {
//                storageSku.append(" ");
//            }
//            if (sku.length() > 0) {
//                sku.append(" ");
//            }
//            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
//            if (orderOutputDo.getCompanyId() == 30) {
//                sku.append(productDo.getCommodityName());
//            } else {
//                sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount()).append(" ");
//            }
            sortResList.add(new OrderOutputProductSortRes(productDo.getStorageSku(), productDo.getCommoditySku(), productDo.getCommodityName(), productDo.getCount(), productDo.getVolume()));
            for (OrderOutputProductRackDto rackDto : rackDtoList) {
                if (rackDto.getPickNumber() == null) {
                    continue;
                }
                rackIdSet.add(rackDto.getRackId());
                rackProductCountMap.merge(rackDto.getRackId() + "_" + (StringUtils.isBlank(rackDto.getPositionName()) ? "M" : rackDto.getPositionName()), rackDto.getPickNumber(), Integer::sum);
            }
        }

        //将sortResList 按 体积排序
        this.sortByVolume(sortResList);
        for (OrderOutputProductSortRes productDo : sortResList) {
            if (storageSku.length() > 0) {
                storageSku.append(" ");
            }
            if (sku.length() > 0) {
                sku.append(" ");
            }
            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
            if (orderOutputDo.getCompanyId() == 30) {
                sku.append(productDo.getCommodityName());
            } else {
                sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount()).append(" ");
            }
        }

        exportVo.setRackCount(rackProductCountMap.size());
        exportVo.setRackCount(rackIdSet.size());

        String position = this.getPosition(rackProductCountMap);
        exportVo.setStorageSku1(position);

        if (sku.length() > 120) {
            exportVo.setCommoditySku(sku.toString());
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
            exportVo.setStorageSku(storageSku.toString());
        } else if (sku.length() > 90) {
            exportVo.setCommoditySku(sku.substring(0, 30));
            exportVo.setCommoditySku1(sku.substring(30, 60));
            exportVo.setStorageSku(sku.substring(60, 90));
//            exportVo.setStorageSku1(sku.substring(90));
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        } else if (sku.length() > 60) {
            exportVo.setCommoditySku(sku.substring(0, 30));
            exportVo.setCommoditySku1(sku.substring(30, 60));
            exportVo.setStorageSku(sku.substring(60));
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        } else if (sku.length() > 30) {
            exportVo.setCommoditySku(sku.substring(0, 30));
            exportVo.setCommoditySku1(sku.substring(30));
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        } else {
            exportVo.setCommoditySku(sku.toString());
            exportVo.setStorageSku(storageSku.toString());
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        }
        if (orderOutputDo.getDeliveryDate() != null)
            if (orderOutputDo.getDeliveryDate().getTime() < System.currentTimeMillis()) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, 1);
                exportVo.setDeliveryDate(TimeUtils.formatDate(calendar.getTime(), "yyyyMMdd"));
            } else {
                exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate(), "yyyyMMdd"));
            }
        if (!"-".equals(orderOutputDo.getDeliveryTime()) || orderOutputDo.getDeliveryTime() != null)
            exportVo.setDeliveryTimeCode(TimeUtils.getSagawaDTimeNew(orderOutputDo.getDeliveryTime()));
        if (orderOutputDo.getCod() != null && orderOutputDo.getCod() != 0) exportVo.setCod(orderOutputDo.getCod() + "");
//        if (orderOutputDo.getStorageId() != 12) {
        exportVo.setCount(orderInputProductDo.getCount() + "");
//        } else {
//            exportVo.setCount(count + "");
//        }
//        wrapper = new QueryWrapper();
//        wrapper.eq("package_id", orderInputProductDo.getId());
        return exportVo;

    }

    private OrderOutputSagawaExportVo buidSagawaExportData(OrderOutputDo orderOutputDo, OrderOutputPackageDo orderInputProductDo) {
        OrderOutputSagawaExportVo exportVo = new OrderOutputSagawaExportVo();
        if (orderOutputDo.getStorageId() == 10 || orderOutputDo.getStorageId() == 11 || orderOutputDo.getStorageId() == 1) {
            exportVo.setE3("146671890039");
            exportVo.setE5("0471-36-1830");
            exportVo.setE6("0471-36-1830");
            exportVo.setE7("278-0002");
            exportVo.setE8("千葉県野田市木野崎字");
            exportVo.setE9("鹿野1788番地２-1");
            if (orderOutputDo.getCompanyId().intValue() == 221) {
                exportVo.setE10("RENOGY JAPAN株式会社");
            }
        } else if (orderOutputDo.getStorageId() == 12) {
            exportVo.setE3("");
            exportVo.setE5("0471361830");
            exportVo.setE6("0471361830");
            exportVo.setE7("6500011");
            exportVo.setE8("兵庫県神戸市中央区下山手通２-");
            exportVo.setE9("１３-３建創ビル８階２０号室");
            exportVo.setE10("EC通販物流センター（関西）");
        }
        if (orderOutputDo.getShopId().intValue() == 1) {
            exportVo.setE10("MWPO（モロ）株式会社(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 2) {
            exportVo.setE10("SCM株式会社(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 3) {
            exportVo.setE10("チチロバ（TITIROBA）楽天市場店");
        } else if (orderOutputDo.getShopId().intValue() == 4) {
            exportVo.setE10("MWPO（モロ）株式会社(楽天)");
        } else if (orderOutputDo.getShopId().intValue() == 6) {
            exportVo.setE10("MWPO（モロ）株式会社公式サイト");
        } else if (orderOutputDo.getShopId().intValue() == 33) {
            exportVo.setE10("EOWO直営店(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 221) {
            exportVo.setE10("lifesia (AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 304) {
            exportVo.setE10("楽天titilife");
        } else if (orderOutputDo.getCompanyId() == 84) {
            exportVo.setE10("チチロバ（TITIROBA）楽天市場店");
        } else if (orderOutputDo.getCompanyId().intValue() == 201) {
            exportVo.setE10("AfterShokz Official Store");
        } else if (orderOutputDo.getCompanyId().intValue() == 80) {
            exportVo.setE10("NIXGIRE LIMITED");
        } else if (orderOutputDo.getCompanyId().intValue() == 323) {
            exportVo.setE10("MamimamiHome");
        } else if (orderOutputDo.getCompanyId().intValue() == 263) {
            exportVo.setE10("UWANT");
        } else if (orderOutputDo.getCompanyId().intValue() == 218) {
            exportVo.setE10("CXWXC");
        } else if (orderOutputDo.getCompanyId().intValue() == 300) {
            exportVo.setE10("Morus(乾燥機)");
            exportVo.setE6("050-5534-9451");
        } else if (orderOutputDo.getCompanyId().intValue() == 221) {
            exportVo.setE10("RENOGY JAPAN株式会社");
            exportVo.setE6("048-299-9264");
            exportVo.setE7("3330866");
            exportVo.setE8("埼玉県川口市芝1丁目");
            exportVo.setE9("30-61F 柳ビル");
        } else if (orderOutputDo.getCompanyId() == 14) {
            exportVo.setE10("OneTigris Camping");
            exportVo.setE7("1580094");
            exportVo.setE8("東京都世田谷区玉川");
            exportVo.setE9("１-１４-１");
        } else if (orderOutputDo.getShopId().intValue() == 395) {
            exportVo.setE10("楽天市場 Greatstar Official");
            exportVo.setE6("0471-36-1830");
        }
        if (StringUtils.isNotBlank(orderOutputDo.getTelPhone())) {
            exportVo.setTelPhone(orderOutputDo.getTelPhone().replaceAll("\\n", "").replaceAll("\\+81", ""));
            if (exportVo.getTelPhone().startsWith("81")) {
                exportVo.setTelPhone(exportVo.getTelPhone().replaceFirst("81", ""));
            }
        }
        exportVo.setPostCode(orderOutputDo.getPostCode().replaceAll("-", "").replaceAll("\\n", ""));
        if (orderOutputDo.getArea() != null) {
            String area = StringsUtil.getJpAreaByEnglishCode(orderOutputDo.getArea());
            orderOutputDo.setAddress((orderOutputDo.getAddress().contains(area) ? "" : area) + orderOutputDo.getAddress().trim().replaceAll("\\n", "").replaceAll("\\t", " ").replaceAll("-", "-").replaceAll("－", "-"));
        } else {
            orderOutputDo.setAddress(orderOutputDo.getAddress().trim().replaceAll("\\n", "").replaceAll("\\t", " ").replaceAll("−", "-").replaceAll("－", "-"));
        }
        if (orderOutputDo.getAddress().length() <= 15) {
            exportVo.setAddress1(orderOutputDo.getAddress());
        } else if (orderOutputDo.getAddress().length() > 15 && orderOutputDo.getAddress().length() <= 30) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 15));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(15));
        } else {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 15));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(15, 30));
            exportVo.setAddress3(orderOutputDo.getAddress().substring(30));
        }
        if (StringUtils.isNotBlank(orderOutputDo.getReceiverName())) {
            orderOutputDo.setReceiverName(orderOutputDo.getReceiverName().replaceAll("\\n", ""));
            if (orderOutputDo.getReceiverName().length() <= 15) {
                exportVo.setReceiverName(orderOutputDo.getReceiverName());
            } else {
                exportVo.setReceiverName(orderOutputDo.getReceiverName().substring(0, 15));
                exportVo.setReceiverName2(orderOutputDo.getReceiverName().substring(15));
            }
        }
//        QueryWrapper<OrderOutputProductDo> wrapper = new QueryWrapper<>();
//        wrapper.eq("package_id", orderInputProductDo.getId());
        int count = 0;
        //此时有对应库位情况，一队多
        List<OrderOutputProductRackDto> productDoList = productDao.getProductRackDto(orderInputProductDo.getId());
        Map<Long, List<OrderOutputProductRackDto>> listMap = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductRackDto::getId));
        StringBuilder sku = new StringBuilder();
        StringBuilder storageSku = new StringBuilder();
        if (listMap.keySet().size() > 1) {
            //yidan duojian
            exportVo.setOrderType(1);
        }
        exportVo.setRackSort(productDoList.get(0).getRackSort());
        exportVo.setShelfSort(productDoList.get(0).getShelfSort());
        Set<Long> rackIdSet = new HashSet<>();

        Map<String, Integer> rackProductCountMap = new HashMap<>();
        List<OrderOutputProductSortRes> sortResList = new ArrayList<>();
        for (Long id : listMap.keySet()) {
            List<OrderOutputProductRackDto> rackDtoList = listMap.get(id);
            OrderOutputProductRackDto productDo = rackDtoList.get(0);
            count = count + productDo.getCount();
//            if (storageSku.length() > 0) {
//                storageSku.append(" ");
//            }
//            if (sku.length() > 0) {
//                sku.append(" ");
//            }
//            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
//            if (orderOutputDo.getCompanyId() == 30) {
//                sku.append(productDo.getCommodityName());
//            } else {
//                sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount()).append(" ");
//            }
            sortResList.add(new OrderOutputProductSortRes(productDo.getStorageSku(), productDo.getCommoditySku(), productDo.getCommodityName(), productDo.getCount(), productDo.getVolume()));
            for (OrderOutputProductRackDto rackDto : rackDtoList) {
                if (rackDto.getPickNumber() == null) {
                    continue;
                }
                rackIdSet.add(rackDto.getRackId());
                rackProductCountMap.merge(rackDto.getRackId() + "_" + (StringUtils.isBlank(rackDto.getPositionName()) ? "M" : rackDto.getPositionName()), rackDto.getPickNumber(), Integer::sum);
            }
        }
        //将sortResList 按 体积排序
        this.sortByVolume(sortResList);
        for (OrderOutputProductSortRes productDo : sortResList) {
            if (storageSku.length() > 0) {
                storageSku.append(" ");
            }
            if (sku.length() > 0) {
                sku.append(" ");
            }
            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
            if (orderOutputDo.getCompanyId() == 30) {
                sku.append(productDo.getCommodityName());
            } else {
                sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount()).append(" ");
            }
        }
        exportVo.setRackCount(rackProductCountMap.size());
        exportVo.setRackCount(rackIdSet.size());
        String position = this.getPosition(rackProductCountMap);
        exportVo.setStorageSku1(position);

        if (sku.length() > 120) {
            exportVo.setCommoditySku(sku.toString());
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
            exportVo.setStorageSku(storageSku.toString());
        } else if (sku.length() > 90) {
            exportVo.setCommoditySku(sku.substring(0, 30));
            exportVo.setCommoditySku1(sku.substring(30, 60));
            exportVo.setStorageSku(sku.substring(60, 90));
//            exportVo.setStorageSku1(sku.substring(90));
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        } else if (sku.length() > 60) {
            exportVo.setCommoditySku(sku.substring(0, 30));
            exportVo.setCommoditySku1(sku.substring(30, 60));
            exportVo.setStorageSku(sku.substring(60));
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        } else if (sku.length() > 30) {
            exportVo.setCommoditySku(sku.substring(0, 30));
            exportVo.setCommoditySku1(sku.substring(30));
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        } else {
            exportVo.setCommoditySku(sku.toString());
            exportVo.setStorageSku(storageSku.toString());
            exportVo.setOrderNumber(orderOutputDo.getOrderOutputNumber());
        }
        if (orderOutputDo.getDeliveryDate() != null)
            if (orderOutputDo.getDeliveryDate().getTime() < System.currentTimeMillis()) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, 1);
                exportVo.setDeliveryDate(TimeUtils.formatDate(calendar.getTime(), "yyyyMMdd"));
            } else {
                exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate(), "yyyyMMdd"));
            }
        if (!"-".equals(orderOutputDo.getDeliveryTime()) || orderOutputDo.getDeliveryTime() != null)
            exportVo.setDeliveryTimeCode(TimeUtils.getSagawaDTime(orderOutputDo.getDeliveryTime()));
        if (orderOutputDo.getCod() != null && orderOutputDo.getCod() != 0) exportVo.setCod(orderOutputDo.getCod() + "");
//        if (orderOutputDo.getStorageId() != 12) {
        exportVo.setCount(orderInputProductDo.getCount() + "");
//        } else {
//            exportVo.setCount(count + "");
//        }
//        wrapper = new QueryWrapper();
//        wrapper.eq("package_id", orderInputProductDo.getId());
        return exportVo;

    }

    private OrderOutputYamatoExportVo buildYamatoExportData(OrderOutputDo orderOutputDo, OrderOutputPackageDo orderInputProductDo) {
        OrderOutputYamatoExportVo exportVo = new OrderOutputYamatoExportVo();
        if (orderOutputDo.getShopId().intValue() == 1) {
            exportVo.setE9("MWPO（モロ）株式会社(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 2) {
            exportVo.setE9("SCM株式会社(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 3) {
            exportVo.setE9("PRORS(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 4) {
            exportVo.setE9("MWPO（モロ）株式会社(楽天)");
        } else if (orderOutputDo.getShopId().intValue() == 6) {
            exportVo.setE9("MWPO（モロ）株式会社公式サイト");
        } else if (orderOutputDo.getShopId().intValue() == 33) {
            exportVo.setE9("EOWO直営店(AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 221) {
            exportVo.setE9("lifesia (AMAZON)");
        } else if (orderOutputDo.getShopId().intValue() == 304) {
            exportVo.setE9("楽天titilife");
        } else if (orderOutputDo.getCompanyId().intValue() == 84) {
            exportVo.setE9("チチロバ楽天市場店");
        } else if (orderOutputDo.getCompanyId().intValue() == 201) {
            exportVo.setE9("AfterShokz Official Store");
        } else if (orderOutputDo.getCompanyId().intValue() == 80) {
            exportVo.setE9("NIXGIRE LIMITED");
        } else if (orderOutputDo.getCompanyId().intValue() == 263) {
            exportVo.setE9("UWANT");
        } else if (orderOutputDo.getCompanyId().intValue() == 218) {
            exportVo.setE9("CXWXC");
        } else if (orderOutputDo.getCompanyId().intValue() == 323) {
            exportVo.setE9("MamimamiHome");
        } else if (orderOutputDo.getCompanyId() == 14) {
            exportVo.setE9("OneTigris Camping");
            exportVo.setE10("1580094");
            exportVo.setE11("東京都世田谷区玉川１-１４-１");
        } else if (orderOutputDo.getCompanyId().intValue() == 221) {
            exportVo.setE9("RENOGY JAPAN株式会社");
            exportVo.setE7("048-299-9264");
            exportVo.setE10("3330866");
            exportVo.setE14("天地無用");
            exportVo.setE11("埼玉県川口市芝1丁目30-61F 柳ビル");
        } else if (orderOutputDo.getShopId().intValue() == 395) {
            exportVo.setE9("楽天市場 Greatstar Official");
            exportVo.setE7("0471-36-1830");
        } else if (orderOutputDo.getCompanyId().intValue() == 300) {
            exportVo.setE9("Morus(乾燥機)");
            exportVo.setE14("天地無用");
            exportVo.setE7("050-5534-9451");
        } else if (orderOutputDo.getCompanyId().intValue() == 263) {
            exportVo.setE9("UWANT");
        }
        exportVo.setSendDate(TimeUtils.formatDate(new Date(), "yyy/MM/dd"));
        if (StringUtils.isNotBlank(orderOutputDo.getTelPhone())) {
            exportVo.setManagerNo(orderOutputDo.getTelPhone().replaceAll("\\+81", ""));
            exportVo.setE2(orderOutputDo.getTelPhone());
            exportVo.setReceiverTelPhone(orderOutputDo.getTelPhone().replaceAll("－", "").replaceAll("-", ""));
        }
        if (StringUtils.isNotBlank(exportVo.getReceiverTelPhone()) && exportVo.getReceiverTelPhone().startsWith("81")) {
            exportVo.setReceiverTelPhone(exportVo.getReceiverTelPhone().replaceFirst("81", ""));
        }
        exportVo.setReceiverName(orderOutputDo.getReceiverName());
        exportVo.setPostCode(orderOutputDo.getPostCode().replaceAll("-", ""));
        orderOutputDo.setAddress(orderOutputDo.getAddress().trim().replaceAll("\\n", "").replaceAll("　", " ").replaceAll("－", "-").replaceAll("−", "-").replaceAll("－", "-"));
        if (orderOutputDo.getArea() != null) {
            String area = StringsUtil.getJpAreaByEnglishCode(orderOutputDo.getArea());
            orderOutputDo.setAddress((orderOutputDo.getAddress().contains(area) ? "" : area) + orderOutputDo.getAddress().trim().replaceAll("\\n", ""));
        } else {

        }
        if (orderOutputDo.getAddress().length() <= 22) {
            exportVo.setAddress1(orderOutputDo.getAddress());
        } else if (orderOutputDo.getAddress().length() <= 37) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 22));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(22));
        } else if (orderOutputDo.getAddress().length() <= 60) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 22));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(22, 37));
            exportVo.setE3(orderOutputDo.getAddress().substring(37));
        } else {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 22));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(22, 37));
            exportVo.setE3(orderOutputDo.getAddress().substring(37, 60));
            exportVo.setE4(orderOutputDo.getAddress().substring(60));
        }
        exportVo.setReceiverName(orderOutputDo.getReceiverName());
        //此时有对应库位情况，一队多
        List<OrderOutputProductRackDto> productDoList = productDao.getProductRackDto(orderInputProductDo.getId());
        Map<Long, List<OrderOutputProductRackDto>> listMap = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductRackDto::getId));
        List<Long> productIdList = productDoList.stream().map(OrderOutputProductRackDto::getProductId).collect(Collectors.toList());
        StringBuilder sku = new StringBuilder();
        StringBuilder storageSku = new StringBuilder();
        if (listMap.keySet().size() > 1) {
            //yidan duojian
            exportVo.setOrderType(1);
        }
        exportVo.setRackSort(productDoList.get(0).getRackSort());
        exportVo.setShelfSort(productDoList.get(0).getShelfSort());
        Set<Long> rackIdSet = new HashSet<>();

        Map<String, Integer> rackProductCountMap = new HashMap<>();
        List<OrderOutputProductSortRes> sortResList = new ArrayList<>();
        for (Long id : listMap.keySet()) {
            List<OrderOutputProductRackDto> rackDtoList = listMap.get(id);
            OrderOutputProductRackDto productDo = rackDtoList.get(0);
//            if (storageSku.length() > 0) {
//                storageSku.append(" ");
//            }
//            if (sku.length() > 0) {
//                sku.append(" ");
//            }
//            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
//            sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
            sortResList.add(new OrderOutputProductSortRes(productDo.getStorageSku(), productDo.getCommoditySku(), productDo.getCommodityName(), productDo.getCount(), productDo.getVolume()));
            for (OrderOutputProductRackDto rackDto : rackDtoList) {
                if (rackDto.getPickNumber() == null) {
                    continue;
                }
                rackIdSet.add(rackDto.getRackId());
                rackProductCountMap.merge(rackDto.getRackId() + "_" + (StringUtils.isBlank(rackDto.getPositionName()) ? "M" : rackDto.getPositionName()), rackDto.getPickNumber(), Integer::sum);
            }
        }
        //将sortResList 按 体积排序
        this.sortByVolume(sortResList);
        boolean isLiPower = liPowerSku(productIdList);
        for (OrderOutputProductSortRes productDo : sortResList) {
            if (storageSku.length() > 0) {
                storageSku.append(" ");
            }
            if (sku.length() > 0) {
                sku.append(" ");
            }
            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
            sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
        }

        exportVo.setRackCount(rackProductCountMap.size());
        exportVo.setRackCount(rackIdSet.size());

//            exportVo.setCommoditySku("");
        exportVo.setCommoditySku(sku.toString());
        exportVo.setCommoditySku(sku.toString());
        exportVo.setStorageSku(storageSku.toString());

        String position = this.getPosition(rackProductCountMap);
        exportVo.setStorageSkuKane(position);
        if (isLiPower) {
            exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber() + "リチウムイオンデンチ");
        } else {
            exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber());
        }
        if (orderOutputDo.getDeliveryDate() != null)
            if (orderOutputDo.getDeliveryDate().getTime() < System.currentTimeMillis()) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, 1);
                exportVo.setDeliveryDate(TimeUtils.formatDate(calendar.getTime(), "yyyy/MM/dd"));
            } else {
                exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate(), "yyyy/MM/dd"));
            }
        exportVo.setDeliveryTimeCode(TimeUtils.getYamatoDTime(orderOutputDo.getDeliveryTime()));
        if (orderOutputDo.getCod() != 0 && orderOutputDo.getCod() != 0) {
            exportVo.setExpressNo("2");
            exportVo.setE16("0");
            exportVo.setE17(orderOutputDo.getCod() + "");
        }
        exportVo.setE18("3");//是否显示序号
        exportVo.setCount(orderInputProductDo.getCount() + "");
        if (DicBusinessItemConstant.yamatoExpressSmall.equals(orderOutputDo.getTrackId())) {
            exportVo.setExpressNo("7");
        } else if (DicBusinessItemConstant.yamatoExpressBox.equals(orderOutputDo.getTrackId())) {
            exportVo.setExpressNo("8");
        }
        return exportVo;

    }

    /**
     * //黑猫临时切换成佐川发货
     *
     * @param productIdList
     * @return
     */
    private boolean liPowerSku(List<Long> productIdList) {
        String s = "4753,4939,5202,5203,5204,5428,7187,7188,8274,8292,8294,8940,11076,11077,11078,11079,12625,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,13051,13079,13262,13288,13351,13352,13353,13354,13355,13356,13384,13392,13414,13439,13593,13594,13609,13905,13924,13925,13966,13967,14468,14517,14588,14606,14607,14722,14859,14860,14861,14862,14863,14864,14865,15058,15143,15144,15145,15152,15167,15221,15222,15257,15258,15259,15260,15355,15387,15415,15628,15749,16037,16039,16047,16053,16336,16337,16361,16440,16742,16743,17419";
        List<String> strings = Arrays.stream(s.split(",")).collect(Collectors.toList());
        for (Long productId : productIdList) {
            if (strings.contains(productId + "")) return true;
        }
        return false;
    }

    /**
     * //黑猫临时切换成佐川发货
     *
     * @param productDoList
     * @return
     */
    private boolean isLiPowerSku(List<OrderOutputProductDo> productDoList) {
        String s = "4753,4939,5202,5428,7187,7188,8292,8294,8940,11076,11077,11078,11079,12625,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,13051,13079,13288,13414,13439,13593,13594,13609,13905,13924,13925,13967,14517,14606,14607,14859,14860,14861,14862,14863,14864,14865,15058,15143,15144,15145,15152,15221,15222,15257,15258,15259,15260,15355,15749,16037,16039,16047,16053,16361,16440,16742,16743,17419";
        List<String> strings = Arrays.stream(s.split(",")).collect(Collectors.toList());
        for (OrderOutputProductDo productDo : productDoList) {
            if (strings.contains(productDo.getProductId() + "")) return true;
        }
        return false;
    }

    private OrderOutputJpPackageExportVo buildJpostPackageExportData(OrderOutputDo orderOutputDo, OrderOutputPackageDo orderInputProductDo) {
        OrderOutputJpPackageExportVo exportVo = new OrderOutputJpPackageExportVo();
        if (StringUtils.isNotBlank(orderOutputDo.getTelPhone())) {
            if (orderOutputDo.getTelPhone().startsWith("81"))
                exportVo.setTelPhone(orderOutputDo.getTelPhone().replaceFirst("81", ""));
            else exportVo.setTelPhone(orderOutputDo.getTelPhone());
        }

        exportVo.setReceiverName(orderOutputDo.getReceiverName());
        if (!orderOutputDo.getReceiverName().contains("様")) {
            exportVo.setReceiverNameKana("様");
        }
        if (orderOutputDo.getCompanyId().intValue() == 84) {
            exportVo.setE19("販売元:チチロバ（TITIROBA）楽天市場店");
        } else if (orderOutputDo.getCompanyId().intValue() == 201) {
            exportVo.setE19("販売元:AfterShokz Official Store");
        } else if (orderOutputDo.getCompanyId() == 80) {
            exportVo.setE19("販売元:NIXGIRE LIMITED");
        } else if (orderOutputDo.getCompanyId().intValue() == 263) {
            exportVo.setE19("販売元:uwant");
        }
        exportVo.setPostCode(orderOutputDo.getPostCode().replaceAll("-", ""));
        JpRegionDo regionDo = mRegionService.getRegionDoByPostCode(orderOutputDo.getPostCode());
        if (regionDo == null) {

        } else {
            exportVo.setRegion(regionDo.getName());
        }
        if (orderOutputDo.getArea() != null) {
            String area = StringsUtil.getJpAreaByEnglishCode(orderOutputDo.getArea());
            orderOutputDo.setAddress((orderOutputDo.getAddress().contains(area) ? "" : area) + orderOutputDo.getAddress().replaceAll("\\n", ""));
        } else {
            orderOutputDo.setAddress(orderOutputDo.getAddress().replaceAll("\\n", ""));
        }
        String address = orderOutputDo.getAddress().replaceAll(regionDo.getName(), "");
        if (address.length() > 30) {
            exportVo.setAddress1(address.substring(0, 15));
            exportVo.setAddress2(address.substring(15, 30));
            exportVo.setAddress3(address.substring(30));
        } else if (address.length() > 15) {
            exportVo.setAddress1(address.substring(0, 15));
            exportVo.setAddress2(address.substring(15));
        } else {
            exportVo.setAddress1(address);
        }

        //此时有对应库位情况，一队多
        List<OrderOutputProductRackDto> productDoList = productDao.getProductRackDto(orderInputProductDo.getId());
        Map<Long, List<OrderOutputProductRackDto>> listMap = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductRackDto::getId));
        StringBuilder sku = new StringBuilder();
        StringBuilder storageSku = new StringBuilder();
        if (listMap.keySet().size() > 1) {
            //yidan duojian
            exportVo.setOrderType(1);
        }
        exportVo.setRackSort(productDoList.get(0).getRackSort());
        exportVo.setShelfSort(productDoList.get(0).getShelfSort());
        Set<Long> rackIdSet = new HashSet<>();

        Map<String, Integer> rackProductCountMap = new HashMap<>();
        List<OrderOutputProductSortRes> sortResList = new ArrayList<>();
        for (Long id : listMap.keySet()) {
            List<OrderOutputProductRackDto> rackDtoList = listMap.get(id);
            OrderOutputProductRackDto productDo = rackDtoList.get(0);
//            if (storageSku.length() > 0) {
//                storageSku.append(" ");
//            }
//            if (sku.length() > 0) {
//                sku.append(" ");
//            }
//            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
//            sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
            sortResList.add(new OrderOutputProductSortRes(productDo.getStorageSku(), productDo.getCommoditySku(), productDo.getCommodityName(), productDo.getCount(), productDo.getVolume()));
            for (OrderOutputProductRackDto rackDto : rackDtoList) {
                if (rackDto.getPickNumber() == null) {
                    continue;
                }
                rackIdSet.add(rackDto.getRackId());
                rackProductCountMap.merge(rackDto.getRackId() + "_" + (StringUtils.isBlank(rackDto.getPositionName()) ? "M" : rackDto.getPositionName()), rackDto.getPickNumber(), Integer::sum);
            }
        }
        //将sortResList 按 体积排序
        this.sortByVolume(sortResList);
        for (OrderOutputProductSortRes productDo : sortResList) {
            if (storageSku.length() > 0) {
                storageSku.append(" ");
            }
            if (sku.length() > 0) {
                sku.append(" ");
            }
            storageSku.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
            sku.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
        }
        exportVo.setRackCount(rackProductCountMap.size());
        exportVo.setRackCount(rackIdSet.size());

        exportVo.setOrderNo(sku.toString());

        String position = this.getPosition(rackProductCountMap);
        exportVo.setSku2(position);
        return exportVo;

    }

    @Override
    public void exportOtherStorageExpress(Map<String, String> map, List<Long> ids, Long currentUserId, HttpServletResponse response) {
        List<OrderOutputDo> orderOutputDoList;
        if (ids != null && ids.size() > 0) {
            orderOutputDoList = this.baseMapper.selectBatchIds(ids);
        } else {
//            response.setStatus(500);
//            return null;
//            orderOutputDoList = this.baseMapper.selectList1(map);
            throw new BizException(SysConstant.Pls_Choose_Order);
        }
        List<OrderOutputSKLExportVo> sklExportVoList = new ArrayList<>();
        List<OrderOutputKSWExportVo> kswExportVoList = new ArrayList<>();
        List<OrderOutputTHKExportVO> thkExportVoList = new ArrayList<>();
        List<OrderOutputKSWExportVo> mtbExportVoList = new ArrayList<>();
        switch (map.get("storageId")) {
            case "1":
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 1).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    if (productDoList != null || productDoList.size() > 0)
                        productDoList.stream().forEach(orderOutputProductDo -> {
                            kswExportVoList.add(buidKswExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                CsvExportParams exportParams2 = new CsvExportParams();
                exportParams2.setCreateHeadRows(true);
                exportParams2.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams2, OrderOutputKSWExportVo.class, kswExportVoList, TimeUtils.getCurrentDateFormat() + "KSW出荷依頼.csv", response);
                break;
            case "2":
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 2).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    if (productDoList != null || productDoList.size() > 0)
                        productDoList.stream().forEach(orderOutputProductDo -> {
                            thkExportVoList.add(buidThkExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                CsvExportParams exportParams4 = new CsvExportParams();
                exportParams4.setCreateHeadRows(true);
                exportParams4.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams4, OrderOutputTHKExportVO.class, thkExportVoList, TimeUtils.getCurrentDateFormat() + "THK出荷依頼.csv", response);
                break;
            case "5":
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 5).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> packageList = productDao.selectList(wrapper1);
                    if (packageList != null || packageList.size() > 0)
                        packageList.stream().forEach(orderOutputProductDo -> {
                            sklExportVoList.add(buidSKLExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                CsvExportParams exportParams1 = new CsvExportParams();
                exportParams1.setCreateHeadRows(true);
                exportParams1.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams1, OrderOutputSKLExportVo.class, sklExportVoList, TimeUtils.getCurrentDateFormat() + "SKL出荷依頼.csv", response);
                break;
            case "11":
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 11).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    if (productDoList != null || productDoList.size() > 0)
                        productDoList.stream().forEach(orderOutputProductDo -> {
                            mtbExportVoList.add(buidKswExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                exportParams2 = new CsvExportParams();
                exportParams2.setCreateHeadRows(true);
                exportParams2.setEncoding("UTF-8");
                CsvUtils.exportCsv(exportParams2, OrderOutputKSWExportVo.class, mtbExportVoList, TimeUtils.getCurrentDateFormat() + "MTB出荷依頼.csv", response);
                break;
        }
        updateOrderCheckStatus(ids, DicBusinessItemConstant.outCreateCheckState, currentUserId);
    }

    private void updateOrderCheckStatus(List<Long> ids, Long outCreateCheckState, Long currentUserId) {
        for (Long orderId : ids) {
            int b = dao.updateOrderCheckId(orderId, DicBusinessItemConstant.outCreateCheckState);
            if (b > 0) {
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_CHECK_ORDER, orderId, currentUserId, 3);
//                operateRecord("审核", orderId, currentUserId);
            }
        }
    }

    /**
     * 定时向SKL仓库发邮件
     */
    @Override
    public void sendMail2SKL() {
        LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderOutputDo::getStatus, DicBusinessItemConstant.outCreateCheckState);
        wrapper.gt(OrderOutputDo::getSendDate, TimeUtils.getCurrentDateFormat(-7));
        wrapper.eq(OrderOutputDo::getStorageId, 5);
        Map<String, String> map = new HashMap<>();
        map.put("storageId", "5");
        List<Long> ids = dao.selectList(wrapper).stream().map(OrderOutputDo::getId).collect(Collectors.toList());
        exportOtherStorageEmailExpress(map, ids, 1L);
        updateOrderWaitSend(map, ids, 1L, null);
    }

    @Override
    public void exportOtherStorageEmailExpress(Map<String, String> map, List<Long> ids, Long currentUserId) {
        String fileName = "", title = "", cotent = "", address = "", cc = "";
        List<OrderOutputDo> orderOutputDoList;
        if (ids != null && ids.size() > 0) {
            orderOutputDoList = this.baseMapper.selectBatchIds(ids);
        } else {
//            response.setStatus(500);
//            return null;
//            orderOutputDoList = this.baseMapper.selectList1(map);
            throw new BizException(SysConstant.Pls_Choose_Order);
        }
        List<OrderOutputSKLExportVo> sklExportVoList = new ArrayList<>();
        List<OrderOutputKSWExportVo> kswExportVoList = new ArrayList<>();
        List<OrderOutputTHKExportVO> thkExportVoList = new ArrayList<>();
        Session session = mailSenderService.initMailSession();
        Transport transport = mailSenderService.initMailTransport(session);
        if (StringUtils.isBlank(map.get("storageId"))) {
            throw new BizException(SysConstant.Pls_Choose_Storage);
        }
        switch (map.get("storageId")) {
            case "1":
                fileName = TimeUtils.getCurrentDateFormat() + "KSW出荷依頼.csv";
                title = "筋斗雲(株)" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報のお知らせ";
                cotent = "新柏倉庫株式会社<br>" + "<br>" + "富澤様<br>" + "<br>" + "いつもお世話になっております。<br>" + "<br>" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報を添付しております。<br>" + "<br>" + "ご確認のほどよろしくお願いいたします。";
                address = "r_tomizawa@shinkashiwa-soko.co.jp";
                cc = "r_tomizawa@shinkashiwa-soko.co.jp,izumi-2@shinkashiwa-soko.co.jp," + "m_kaneko@shinkashiwa-soko.co.jp,y_katsumata@shinkashiwa-soko.co.jp,service@cloudkinto.com," + "hujingwen@sanchoum.com>,eutopia@cloudkinto.com";
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 1).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    if (productDoList != null || productDoList.size() > 0)
                        productDoList.stream().forEach(orderOutputProductDo -> {
                            kswExportVoList.add(buidKswExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                CsvExportParams exportParams2 = new CsvExportParams();
                exportParams2.setCreateHeadRows(true);
                exportParams2.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams2, OrderOutputKSWExportVo.class, kswExportVoList, fileName, filePath);
                break;
            case "2":
                fileName = TimeUtils.getCurrentDateFormat() + "KSW出荷依頼.csv";
                title = "筋斗雲(株)" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報のお知らせ";
                cotent = "シンク株式会社<br>" + "<br>" + "山本様<br>" + "<br>" + "いつもお世話になっております。<br>" + "<br>" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報を添付しております。<br>" + "<br>" + "ご確認のほどよろしくお願いいたします。";
                address = "yamamoto@think21.co.jp";
                cc = "service@cloudkinto.com,hujingwen@sanchoum.com,eutopia@cloudkinto.com";
                fileName = TimeUtils.getCurrentDateFormat() + "THK出荷依頼.csv";
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 2).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    if (productDoList != null || productDoList.size() > 0)
                        productDoList.stream().forEach(orderOutputProductDo -> {
                            thkExportVoList.add(buidThkExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                CsvExportParams exportParams4 = new CsvExportParams();
                exportParams4.setCreateHeadRows(true);
                exportParams4.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams4, OrderOutputTHKExportVO.class, thkExportVoList, fileName, filePath);
                break;
            case "5":
                fileName = TimeUtils.getCurrentDateFormat() + "KSW出荷依頼.csv";
                title = "筋斗雲(株)" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報のお知らせ";
                cotent = "エスケーロジ株式会社<br>" + "<br>" + "後藤 様<br>" + "<br>" + "いつもお世話になっております。<br>" + "<br>" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報を添付しております。<br>" + "<br>" + "ご確認のほどよろしくお願いいたします。";
                address = "d-gotou@sklg.co.jp";
                cc = "t-tsuyutani@sklg.co.jp,service@cloudkinto.com,hujingwen@sanchoum.com,eutopia@cloudkinto.com";
                fileName = TimeUtils.getCurrentDateFormat() + "SKL出荷依頼.csv";
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 5).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> packageList = productDao.selectList(wrapper1);
                    if (packageList != null || packageList.size() > 0)
                        packageList.stream().forEach(orderOutputProductDo -> {
                            sklExportVoList.add(buidSKLExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                CsvExportParams exportParams1 = new CsvExportParams();
                exportParams1.setCreateHeadRows(true);
                exportParams1.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams1, OrderOutputSKLExportVo.class, sklExportVoList, fileName, filePath);
                break;
            case "11":
                title = "筋斗雲(株)" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報のお知らせ";
                cotent = "エスケーロジ株式会社<br>" + "<br>" + "童 様<br>" + "<br>" + "いつもお世話になっております。<br>" + "<br>" + TimeUtils.getCurrentDateFormat("MM月dd日") + "btoc出荷情報を添付しております。<br>" + "<br>" + "ご確認のほどよろしくお願いいたします。";
                address = "service@cloudkinto.com";
                cc = "";
                fileName = TimeUtils.getCurrentDateFormat() + "MTB出荷依頼.csv";
                orderOutputDoList.stream().filter(orderOutputDo -> orderOutputDo.getStorageId() == 11).sorted(new Comparator<OrderOutputDo>() {
                    @Override
                    public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                        if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                        return o1.getCommoditySku().compareTo(o2.getCommoditySku());
                    }
                }).forEach(orderOutputDo -> {
                    QueryWrapper wrapper1 = new QueryWrapper();
                    wrapper1.eq("order_id", orderOutputDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    if (productDoList != null || productDoList.size() > 0)
                        productDoList.stream().forEach(orderOutputProductDo -> {
                            kswExportVoList.add(buidKswExportData(orderOutputDo, orderOutputProductDo));
                        });
                });
                exportParams2 = new CsvExportParams();
                exportParams2.setCreateHeadRows(true);
                exportParams2.setEncoding("Shift-JIS");
                CsvUtils.exportCsv(exportParams2, OrderOutputKSWExportVo.class, kswExportVoList, fileName, filePath);
                break;
        }
        String finalTitle = title;
        String finalContent = cotent;
        String finalCc = cc;
        String finalAddress = address;
        String finalFileName = fileName;
        threadPoolTaskExecutor.execute(() -> {
            mailSenderService.sendFileEmail(session, transport, finalTitle, TimeUtils.getCurrentDateFormat() + "出荷依頼.csv", finalContent, "text/html;charset=Shift-JIS", finalAddress, finalCc, filePath + File.separator + finalFileName);
        });
//        updateOrderCheckStatus(ids, DicBusinessItemConstant.outCreateCheckState, currentUserId);
    }

    @Override
    public void exportTrackJPostExpress(Map<String, String> map, List<Long> ids, Long currentUserId, HttpServletResponse response) {
        List<OrderOutputDo> orderOutputDoList;
        if (ids != null && ids.size() > 0) {
            orderOutputDoList = this.baseMapper.selectBatchIds(ids);
        } else {
            orderOutputDoList = this.baseMapper.selectList1(map);
        }

        List<OrderOutputJpCommonExportVo> jpCommonExportVoList = new ArrayList<>();
        List<OrderOutputJpCodExportVo> jpCodExportVoList = new ArrayList<>();
        orderOutputDoList.stream().sorted(new Comparator<OrderOutputDo>() {
            @Override
            public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                return o1.getCommoditySku().compareToIgnoreCase(o2.getCommoditySku());
            }
        }).forEach(orderOutputDo -> {
            QueryWrapper<OrderOutputPackageDo> wrapper1 = new QueryWrapper<>();
            wrapper1.eq("order_output_id", orderOutputDo.getId());
            List<OrderOutputPackageDo> packageList = packageDao.selectList(wrapper1);
            for (OrderOutputPackageDo orderOutputPackageDo : packageList) {
                if (orderOutputDo.getCod() != null && orderOutputDo.getCod() != 0) {
                    jpCodExportVoList.add((OrderOutputJpCodExportVo) buidJPostCodExportData(orderOutputDo, orderOutputPackageDo));
                } else {
                    jpCommonExportVoList.add((OrderOutputJpCommonExportVo) buidJPost2ExportData(orderOutputDo, orderOutputPackageDo));
                }
            }
        });
        ExportParams exportParams1 = new ExportParams();
        exportParams1.setCreateHeadRows(true);
        exportParams1.setSheetName("Cod");
        Map<String, Object> jpCodMap = new HashMap<>();
        jpCodMap.put("title", exportParams1);
        jpCodMap.put("entity", OrderOutputJpCodExportVo.class);
        jpCodMap.put("data", jpCodExportVoList);
        ExportParams exportParams2 = new ExportParams();
        exportParams2.setCreateHeadRows(true);
        exportParams2.setSheetName("Common");
        Map<String, Object> jpCommonMap = new HashMap<>();
        jpCommonMap.put("title", exportParams2);
        jpCommonMap.put("entity", OrderOutputJpCommonExportVo.class);
        jpCommonMap.put("data", jpCommonExportVoList);
        List<Map<String, Object>> sheetsList = new ArrayList<>();
        sheetsList.add(jpCodMap);
        sheetsList.add(jpCommonMap);
        try {
            ExcelUtils.exportExcel(sheetsList, TimeUtils.getCurrentDateFormat() + "JPOst出荷依頼.xls", response);
        } catch (IOException e) {
            e.printStackTrace();
        }
        updateOrderCheckStatus(ids, DicBusinessItemConstant.outCreateCheckState, currentUserId);
    }

    private OrderOutputJPVo buidJPostCodExportData(OrderOutputDo orderOutputDo, OrderOutputPackageDo packageDo) {
        OrderOutputJpCodExportVo exportVo = new OrderOutputJpCodExportVo();
        exportVo.setSendDate(TimeUtils.formatDate(orderOutputDo.getSendDate(), "yyyy/MM/dd"));
        exportVo.setPostCode(orderOutputDo.getPostCode());
        exportVo.setTelPhone(orderOutputDo.getTelPhone());
        if (orderOutputDo.getAddress().length() > 51) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 17));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(17, 34));
            exportVo.setAddress3(orderOutputDo.getAddress().substring(34, 51));

        } else if (orderOutputDo.getAddress().length() > 34) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 17));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(17, 34));
            exportVo.setAddress3(orderOutputDo.getAddress().substring(34));

        } else if (orderOutputDo.getAddress().length() > 17) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 17));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(17));

        } else {
            exportVo.setAddress1(orderOutputDo.getAddress());
        }
        exportVo.setOrderName(orderOutputDo.getReceiverName());

        int count = 0;
        //此时有对应库位情况，一队多
        List<OrderOutputProductRackDto> productDoList = productDao.getProductRackDto(packageDo.getId());
        Map<Long, List<OrderOutputProductRackDto>> listMap = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductRackDto::getId));
        StringBuilder stringBuilder = new StringBuilder();
        if (listMap.keySet().size() > 1) {
            //yidan duojian
            exportVo.setOrderType(1);
        }
        exportVo.setRackSort(productDoList.get(0).getRackSort());
        exportVo.setShelfSort(productDoList.get(0).getShelfSort());
        Set<Long> rackIdSet = new HashSet<>();

        Map<String, Integer> rackProductCountMap = new HashMap<>();
        List<OrderOutputProductSortRes> sortResList = new ArrayList<>();
        for (Long id : listMap.keySet()) {
            List<OrderOutputProductRackDto> rackDtoList = listMap.get(id);
            OrderOutputProductRackDto productDo = rackDtoList.get(0);
            count += productDo.getCount();
//            if (stringBuilder.length() > 0) {
//                stringBuilder.append(",");
//            }
//            if (orderOutputDo.getCompanyId() == 30) {
//                stringBuilder.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
//            } else {
//                stringBuilder.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
//            }
            sortResList.add(new OrderOutputProductSortRes(productDo.getStorageSku(), productDo.getCommoditySku(), productDo.getCommodityName(), productDo.getCount(), productDo.getVolume()));
            exportVo.setProductName(productDo.getCommodityName());
            for (OrderOutputProductRackDto rackDto : rackDtoList) {
                if (rackDto.getPickNumber() == null) {
                    continue;
                }
                rackIdSet.add(rackDto.getRackId());
                rackProductCountMap.merge(rackDto.getRackId() + "_" + (StringUtils.isBlank(rackDto.getPositionName()) ? "M" : rackDto.getPositionName()), rackDto.getPickNumber(), Integer::sum);
            }
        }

        //将sortResList 按 体积排序
        this.sortByVolume(sortResList);
        for (OrderOutputProductSortRes productDo : sortResList) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append(",");
            }
            if (orderOutputDo.getCompanyId() == 30) {
                stringBuilder.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
            } else {
                stringBuilder.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
            }
        }

        exportVo.setRackCount(rackProductCountMap.size());
        exportVo.setRackCount(rackIdSet.size());
        String position = this.getPosition(rackProductCountMap);
        exportVo.setPosition(position);

        exportVo.setCommoditySku(stringBuilder.toString());
        exportVo.setCount(count + "");
        if (orderOutputDo.getCompanyId() == 30L) {
            exportVo.setOrderNo(orderOutputDo.getOrderNo());
        } else {
            exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber());
        }
        if (orderOutputDo.getDeliveryDate() != null) {
            exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate()));
        }
        exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
        exportVo.setTips(orderOutputDo.getTips());
        exportVo.setTrackNumber(orderOutputDo.getTrackNumber());
        exportVo.setId(orderOutputDo.getId() + "");
        if (orderOutputDo.getCod() != null && orderOutputDo.getCod() != 0) {
            exportVo.setCod(orderOutputDo.getCod() + "");
        }
        return exportVo;
    }

    private OrderOutputJPVo buidJPost2ExportData(OrderOutputDo orderOutputDo, OrderOutputPackageDo packageDo) {
        OrderOutputJpCommonExportVo exportVo = new OrderOutputJpCommonExportVo();
        exportVo.setSendDate(TimeUtils.formatDate(orderOutputDo.getSendDate(), "yyyy/MM/dd"));
        exportVo.setPostCode(orderOutputDo.getPostCode());
        exportVo.setTelPhone(orderOutputDo.getTelPhone());
        if (orderOutputDo.getAddress().length() > 54) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 17));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(17, 34));
            exportVo.setAddress3(orderOutputDo.getAddress().substring(34, 51));
        } else if (orderOutputDo.getAddress().length() > 34) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 17));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(17, 34));
            exportVo.setAddress3(orderOutputDo.getAddress().substring(34));

        } else if (orderOutputDo.getAddress().length() > 17) {
            exportVo.setAddress1(orderOutputDo.getAddress().substring(0, 17));
            exportVo.setAddress2(orderOutputDo.getAddress().substring(17));

        } else {
            exportVo.setAddress1(orderOutputDo.getAddress());
        }
        if (orderOutputDo.getReceiverName().length() > 17) {
            exportVo.setOrderName(orderOutputDo.getReceiverName().substring(0, 17));
        } else {
            exportVo.setOrderName(orderOutputDo.getReceiverName());
        }

        int count = 0;
        //此时有对应库位情况，一队多
        List<OrderOutputProductRackDto> productDoList = productDao.getProductRackDto(packageDo.getId());
        Map<Long, List<OrderOutputProductRackDto>> listMap = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductRackDto::getId));
        StringBuilder stringBuilder = new StringBuilder();
        if (listMap.keySet().size() > 1) {
            //yidan duojian
            exportVo.setOrderType(1);
        }
        exportVo.setRackSort(productDoList.get(0).getRackSort());
        exportVo.setShelfSort(productDoList.get(0).getShelfSort());
        Set<Long> rackIdSet = new HashSet<>();

        Map<String, Integer> rackProductCountMap = new HashMap<>();
        List<OrderOutputProductSortRes> sortResList = new ArrayList<>();
        for (Long id : listMap.keySet()) {
            List<OrderOutputProductRackDto> rackDtoList = listMap.get(id);
            OrderOutputProductRackDto productDo = rackDtoList.get(0);
            count += productDo.getCount();
//            if (stringBuilder.length() > 0) {
//                stringBuilder.append(",");
//            }
//            if (orderOutputDo.getCompanyId() == 30) {
//                stringBuilder.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
//            } else {
//                stringBuilder.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
//            }
            exportVo.setProductName(productDo.getCommodityName());
            sortResList.add(new OrderOutputProductSortRes(productDo.getStorageSku(), productDo.getCommoditySku(), productDo.getCommodityName(), productDo.getCount(), productDo.getVolume()));
            for (OrderOutputProductRackDto rackDto : rackDtoList) {
                if (rackDto.getPickNumber() == null) {
                    continue;
                }
                rackIdSet.add(rackDto.getRackId());
                rackProductCountMap.merge(rackDto.getRackId() + "_" + (StringUtils.isBlank(rackDto.getPositionName()) ? "M" : rackDto.getPositionName()), rackDto.getPickNumber(), Integer::sum);
            }
        }
        //将sortResList 按 体积排序
        this.sortByVolume(sortResList);
        for (OrderOutputProductSortRes productDo : sortResList) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append(",");
            }
            if (orderOutputDo.getCompanyId() == 30) {
                stringBuilder.append(productDo.getStorageSku()).append("*").append(productDo.getCount());
            } else {
                stringBuilder.append(productDo.getCommoditySku()).append("*").append(productDo.getCount());
            }
        }

        exportVo.setRackCount(rackProductCountMap.size());
        exportVo.setRackCount(rackIdSet.size());
        String position = this.getPosition(rackProductCountMap);
        exportVo.setPosition(position);

        exportVo.setCommoditySku(stringBuilder.toString());
        exportVo.setCount(count + "");
        exportVo.setOrderNo(orderOutputDo.getOrderOutputNumber());
        if (orderOutputDo.getDeliveryDate() != null) {
            exportVo.setDeliveryDate(TimeUtils.formatDate(orderOutputDo.getDeliveryDate()));
        }
        exportVo.setDeliveryTime(orderOutputDo.getDeliveryTime());
        exportVo.setTips(orderOutputDo.getTips());
        exportVo.setTrackNumber(orderOutputDo.getTrackNumber());
        exportVo.setId(orderOutputDo.getId() + "");

        return exportVo;
    }

    @Override
    public void batchSendApi(String[] ids, Long userId) {
        for (String id : ids) {
            OrderOutputDo et = dao.selectById(id);
            if (et == null || !DicBusinessItemConstant.outToCheck.equals(et.getStatus()) || et.getPickUpId() == null) {
                continue;
            }
            OrderOutputUpdateTrackNumberReq req = new OrderOutputUpdateTrackNumberReq();
            req.setId(et.getId());
            req.setOrderOutputNumber(et.getOrderOutputNumber());
            req.setChecked(true);
            req.setTrackId(et.getTrackId());
            req.setTrackNumber(et.getTrackNumber());
            this.updateTrackNumber(req, userId, et.getCompanyId());
        }
    }

    /**
     * 发货 2023-02-02 需求：单个发货 在未确认复核的情况下，都修改状态成 待复核，待复核状态的发货才去扣减库存
     *
     * @param req
     * @param userId
     * @param companyId
     * @return
     */
    @Override
    public SingleResult updateTrackNumber(OrderOutputUpdateTrackNumberReq req, Long userId, Long companyId) {
        OrderOutputDo orderOutputDo = dao.selectById(req.getId());
        if (orderOutputDo == null) {
            throw new BizException(SysConstant.Order_NotExist1);
        }
        if (!orderOutputDo.getTrackId().equals(req.getTrackId())) {
            orderOutputDo.setTrackId(req.getTrackId());
            orderOutputDo.setUpdateTime(new Date());
            orderOutputDo.setUpdateBy(userId);
        }
        if (StringUtils.isNotBlank(req.getTrackNumber())) {
            //待复核状态
            if (DicBusinessItemConstant.outToCheck.equals(orderOutputDo.getStatus())) {
                orderOutputDo.setTrackNumber(req.getTrackNumber());
                if (req.isChecked()) {
                    //且 确认复核通过 去扣减库存 更改状态为已发货
                    if (orderOutputDo.getPickUpId() == null) {//无拣货单
                        if (req.getPositionAndNumberList() == null) {
                            throw new BizException(SysConstant.OrderOutput_NoSuggest_Rack);
                        }
                        this.sendWhenOutWaitSendOut(req.getPositionAndNumberList(), orderOutputDo, userId);

                    } else {
                        //扣旧表库存
                        dealwithOrderSendOut(orderOutputDo, userId);
                    }
                    this.calFeeAfterSend(orderOutputDo, userId);
                }
            } else { //其他状态
                orderOutputDo.setTrackNumber(req.getTrackNumber());
                boolean checked = false;
                if (DicBusinessItemConstant.alreadyPickUp.equals(orderOutputDo.getStatus()) || DicBusinessItemConstant.waitingPickUp.equals(orderOutputDo.getStatus())) {
                    //已拣货 已经锁定库存
                    if (req.isChecked()) {
                        //确认复核 直接发货
                        dealwithOrderSendOut(orderOutputDo, userId);
                        this.calFeeAfterSend(orderOutputDo, userId);
                    } else {
                        //未确认复核 修改状态为 待复核
                        orderOutputDo.setStatus(DicBusinessItemConstant.outToCheck);
                        checked = true;
                    }
                }
//                else if (DicBusinessItemConstant.waitingPickUp.equals(orderOutputDo.getStatus())) {
//                    //待拣货发货 先去锁定库存，再去发货
//                    StockPickUpDo pickUpDo = stockPickUpDao.selectById(orderOutputDo.getPickUpId());
//                    if (pickUpDo == null) {
//                        throw new BizException(SysConstant.OrderOutput_Pickup_NotMatch_OrderNo, orderOutputDo.getOrderOutputNumber());
//                    }
//                    stockPickUpService.finishPickUp(pickUpDo, new HashSet<>(), userId, orderOutputDo.getId());
//                    if (req.isChecked()) {
//                        //确认复核 直接发货
//                        dealwithOrderSendOut(orderOutputDo, userId);
//                        this.calFeeAfterSend(orderOutputDo, userId);
//                    } else {
//                        //未确认复核 修改状态为 待复核
//                        orderOutputDo.setStatus(DicBusinessItemConstant.outToCheck);
//                        checked = true;
//                    }
//                }
                else if (DicBusinessItemConstant.orderCutOff.equals(orderOutputDo.getStatus())) {
                    if (req.isChecked()) {
                        //判断是发货前 截单还是发货后截单
                        ProductOutDo outDo = productOutDao.selectOne(new LambdaQueryWrapper<ProductOutDo>().eq(ProductOutDo::getOutNo, orderOutputDo.getOrderNo()).eq(ProductOutDo::getCompanyId, orderOutputDo.getCompanyId()).last(" order by id desc limit 1"));
                        if (outDo == null) {
                            //说明是 发货前截单  需要操作库存
                            if (orderOutputDo.getPickUpId() != null) {
                                dealwithOrderSendOut(orderOutputDo, userId);
                            } else {
                                //没有 关联拣货单
                                BatchPickUpReq pickUpReq = new BatchPickUpReq();
                                pickUpReq.setIds(Arrays.asList(orderOutputDo.getId()));
                                List<BatchPickUpRes> resList = new ArrayList<>();
                                try {
                                    //获取出库推荐库位
                                    resList = this.batchPickUp(pickUpReq, userId, orderOutputDo.getCompanyId());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                if (resList == null || resList.size() == 0) {
                                    throw new BizException(SysConstant.OrderOutput_Stock_NotEnough_OrderNo, orderOutputDo.getOrderOutputNumber());
                                }
                                this.sendWhenOutWaitSendOut(resList.get(0).getPositionAndNumberList(), orderOutputDo, userId);
//                                orderOutputDo.setPickUpId(0L);//0代表已发未拣货
                            }
                        }
                        this.calFeeAfterSend(orderOutputDo, userId);
                    } else {
                        throw new BizException(SysConstant.OrderOutput_Confirm_Check);
                    }
                } else if (orderOutputDo.getStatus().equals(DicBusinessItemConstant.problemShipment)) {
                    if (req.isChecked()) {
                        //问题件只算费用，不发货
                        this.calFeeAfterSend(orderOutputDo, userId);
                    } else {
                        throw new BizException(SysConstant.OrderOutput_Confirm_Check);
                    }
                } else if (DicBusinessItemConstant.outWaitSendOut.equals(orderOutputDo.getStatus())) {
                    if (req.isChecked()) {
                        //已打单发货 分两种，一种拣货单，一种没有拣货单
                        if (orderOutputDo.getPickUpId() == null) {//无拣货单
                            if (req.getPositionAndNumberList() == null) {
                                throw new BizException(SysConstant.OrderOutput_NoSuggest_Rack);
                            }
                            this.sendWhenOutWaitSendOut(req.getPositionAndNumberList(), orderOutputDo, userId);
//                            orderOutputDo.setPickUpId(0L);//0代表已发未拣货
//                            dao.updateById(orderOutputDo);
                        } else {
                            //扣旧表库存
                            dealwithOrderSendOut(orderOutputDo, userId);
                        }
                        this.calFeeAfterSend(orderOutputDo, userId);
                    } else {
                        orderOutputDo.setStatus(DicBusinessItemConstant.outToCheck);
                        checked = true;
                    }
                } else {
                    orderOutputDo.setTrackNumber(req.getTrackNumber());
                }
                if (checked) {
                    operateRecordDao.operateAddRecordAndValue(SysConstant.OPERATE_UPDATE_ORDER_NUMBER, orderOutputDo.getTrackNumber(), orderOutputDo.getId(), userId, 3);
//                    this.operateRecord2(String.format("更新了单号：%s", orderOutputDo.getTrackNumber()), orderOutputDo.getId(), userId);
                }
            }
        } else {
            orderOutputDo.setTrackNumber(req.getTrackNumber());
        }
        dao.updateById(orderOutputDo);
        return null;
    }

    /**
     * 已打单状态直接发货
     *
     * @param positionAndNumberList
     * @param orderOutputDo
     * @param userId
     */
    public void sendWhenOutWaitSendOut(List<PositionAndNumberDTO> positionAndNumberList, OrderOutputDo orderOutputDo, Long userId) {

        //已打单状态 直接发货, 不需要锁定库位，随机分配库位，获取方法调用朱加乐得接口,直接去扣库存
        for (PositionAndNumberDTO positionAndNumberDTO : positionAndNumberList) {
            ProductStockRackDo stockRackDo = productStockRackDao.selectById(positionAndNumberDTO.getStockRackId());
            if (stockRackDo == null) {
                throw new BizException(SysConstant.Order_StockRack_NotExist);
            }
            if (stockRackDo.getStore() == 1) {
                //配货区库存无法直接发货，请先调货
                throw new BizException(SysConstant.Order_StockRack_Store);
            }
            if (stockRackDo.getGoodQuantity() < positionAndNumberDTO.getNumber()) {
                throw new BizException(SysConstant.Order_StockRack_NotEnough);
            }
//            stockRackDo.setGoodQuantity(stockRackDo.getGoodQuantity() - positionAndNumberDTO.getNumber());
//                    productStockRackDao.updateById(stockRackDo);
            productStockRackDao.updateStockById(stockRackDo.getId(), positionAndNumberDTO.getNumber());

            //插入出库记录,并操作旧表库存
            productOutService.dealWithStock(stockRackDo.getStockId(), positionAndNumberDTO.getProductId(), orderOutputDo.getStorageId(), orderOutputDo.getShopId(), orderOutputDo.getCompanyId(), userId, positionAndNumberDTO.getNumber(), orderOutputDo.getOrderOutputNumber(), orderOutputDo.getOrderNo(), "output", "output", true);
            if (stockRackDo.getGoodQuantity() == 0 && stockRackDo.getBadQuantity() == 0 && stockRackDo.getGoodLockQuantity() == 0 && stockRackDo.getBadLockQuantity() == 0) {
                productStockRackDao.deleteById(stockRackDo);
                int count = productStockRackDao.selectCount(new LambdaQueryWrapper<ProductStockRackDo>().eq(ProductStockRackDo::getStockId, stockRackDo.getStockId()).orderByDesc(ProductStockRackDo::getRackId));
                if (count == 0) {
                    productStockDao.deleteById(stockRackDo.getStockId());
                }
            }


            //并插入流水 库存流水新
            productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.Output.getValue(), orderOutputDo.getOrderOutputNumber(), orderOutputDo.getShopId(), positionAndNumberDTO.getProductId(), orderOutputDo.getStorageId(), -positionAndNumberDTO.getNumber(), 0, 0, positionAndNumberDTO.getRackId(), orderOutputDo.getCompanyId(), userId, userId == null ? "SKL 系统自动发货" : "出库单 已打单 直接发货");

        }
//        orderOutputDo.setPickUpId(0L);//0代表已发未拣货
//        dao.updateById(orderOutputDo);

    }

    /**
     * 计算费用并修改状态为 已发货
     *
     * @param orderOutputDo
     * @param userId
     */
    public void calFeeAfterSend(OrderOutputDo orderOutputDo, Long userId) {
        threadPoolTaskExecutor.execute(() -> {
            this.calFeeAfterSendSingleThread(orderOutputDo, userId);
        });
    }

    public void calFeeAfterSendSingleThread(OrderOutputDo orderOutputDo, Long userId) {
        try {
            double total = dealwithOrderSendOutShipFeeFix(orderOutputDo, 1, userId);
            mCostService.add(0, orderOutputDo.getOrderOutputNumber() + "订单出库", total, orderOutputDo.getShopId(), orderOutputDo.getCompanyId(), orderOutputDo.getId());
        } catch (Exception e) {
            e.printStackTrace();
            orderOutputDo.setStatus(DicBusinessItemConstant.problemShipment);
            orderOutputDo.setSendTime(new Date());
            updateById(orderOutputDo);
        }
        //日志操作
        operateRecordDao.operateAddRecordAndValue(SysConstant.OPERATE_SEND_ORDER_NUMBER, orderOutputDo.getTrackNumber(), orderOutputDo.getId(), userId, 3);
//        operateRecord2(String.format("发货了出库订单,单号：%s", orderOutputDo.getTrackNumber()), orderOutputDo.getId(), userId);
    }


    /**
     * 待复核发货
     */
    public synchronized Boolean outToCheckSend(BatchPickUpReq pickUpReq, OrderOutputDo orderOutputDo, Long userId) {
//        List<BatchPickUpRes> resList = new ArrayList<>();
//        //获取出库推荐库位
//        resList = this.batchPickUp(pickUpReq, userId, orderOutputDo.getCompanyId());
//        if (resList == null || resList.size() == 0) {
////                operateRecord2(String.format("发货失败, 单号：%s,原因:库存不足", orderOutputDo.getTrackNumber()), orderOutputDo.getId(), userId);
//            return false;
//        }
//        this.sendWhenOutWaitSendOut(resList.get(0).getPositionAndNumberList(), orderOutputDo, userId);
        return true;
    }

    @Override
    public boolean back2Stock(Long id, String fee, String type, Long userId) {

        return false;
    }

    @Override
    public OrderOutputUpdateTrackNumberRes updateTrackNumberInit(Long id, Long userId, Long companyId) {
        OrderOutputDo orderOutputDo = dao.selectById(id);
        if (orderOutputDo == null) {
            throw new BizException(SysConstant.Order_NotExist1);
        }
        OrderOutputUpdateTrackNumberRes res = new OrderOutputUpdateTrackNumberRes();
        res.setId(id);
        res.setCurrentTrackId(orderOutputDo.getTrackId());
        res.setTrackNumber(orderOutputDo.getTrackNumber());
        LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.trackCompany);
        List<DicBusinessItemDo> trackCompanyList = dicBusinessItemDao.selectList(wrapper);
        List<IdAndNameEntity> trackList = new ArrayList<>();
        for (DicBusinessItemDo itemDo : trackCompanyList) {
            trackList.add(new IdAndNameEntity(itemDo.getId().intValue(), itemDo.getDicItemValue()));
        }
        res.setTrackIds(trackList);

        //只有已打单得时候 才展示推荐出库库位
        if ((DicBusinessItemConstant.outWaitSendOut.equals(orderOutputDo.getStatus()) || DicBusinessItemConstant.outToCheck.equals(orderOutputDo.getStatus())) && orderOutputDo.getPickUpId() == null) {
            BatchPickUpReq pickUpReq = new BatchPickUpReq();
            pickUpReq.setIds(Arrays.asList(id));
            List<BatchPickUpRes> resList = this.batchPickUp(pickUpReq, userId, companyId);
            if (resList == null || resList.size() == 0) {
                throw new BizException(SysConstant.Product_Stock_NotEnough);
            }
            res.setShowList(resList.get(0).getShowList());
            res.setPositionAndNumberList(resList.get(0).getPositionAndNumberList());
        } else if (DicBusinessItemConstant.alreadyPickUp.equals(orderOutputDo.getStatus()) || DicBusinessItemConstant.waitingPickUp.equals(orderOutputDo.getStatus()) || ((DicBusinessItemConstant.outWaitSendOut.equals(orderOutputDo.getStatus()) || DicBusinessItemConstant.outToCheck.equals(orderOutputDo.getStatus())) && orderOutputDo.getPickUpId() != null)) {
            StockPickUpDo pickUpDo = stockPickUpDao.selectById(orderOutputDo.getPickUpId());
            if (pickUpDo == null) {
                throw new BizException(SysConstant.OrderOutput_Pickup_NotMatch_OrderNo, orderOutputDo.getOrderOutputNumber());
            }
            StorageDo storageDo = storageDao.selectById(orderOutputDo.getStorageId());
            if (storageDo == null) {
                throw new BizException(SysConstant.Storage_NotExist);
            }
            List<PositionAndNumberDTO> positionAndNumberList = new ArrayList<>();
//            if (DicBusinessItemConstant.waitingPickUp.equals(orderOutputDo.getStatus())) {
//                //待拣货 重新根据库位 匹配库存
//                positionAndNumberList = stockPickUpService.getPosList(pickUpDo, new HashSet<>(), orderOutputDo.getId(), true);
//            } else {
            //已拣货 和 已打单且已关联拣货单 锁定了库存，获取锁定库存信息
            positionAndNumberList = stockPickUpService.getPostListByOrderId(pickUpDo, id, storageDo.getStorageName());
//            }
            res.setPositionAndNumberList(positionAndNumberList);
            res.setShowList(stockPickUpService.getShowList(positionAndNumberList));
        }
        return res;
    }

    @Override
    public void exportSkuTotal(Map<String, String> map, List<Long> ids, Long currentUserId, HttpServletResponse response) {
        if (ids == null) ids = new ArrayList<>();
        final List<Long> orderIdsList = ids;
        if (orderIdsList.size() < 1) {
            List<OrderOutputDo> orderList = dao.selectList1(map);
            if (orderList == null) {
                throw new BizException(SysConstant.No_Data);
            }
            orderList.stream().forEach(orderOutputDo -> {
                orderIdsList.add(orderOutputDo.getId());
            });
        }
        Integer todayCount = (Integer) redisTemplate.opsForValue().get(ORDER_SKU_SUBTOTAL_CODE_KEY + TimeUtils.getCurrentDateFormat("MMdd"));
        if (todayCount == null) {
            todayCount = 0;
        }
        OrderOutputSkuSumExcelExportVo excelExportVo1 = new OrderOutputSkuSumExcelExportVo();
        StorageDo storageDo = storageDao.selectById(map.get("storageId"));

        if (storageDo != null) excelExportVo1.setStorageSku(storageDo.getCode());
        if ("1".equals(map.get("multi"))) {
            excelExportVo1.setCommoditySku("一单一件");
        } else if ("2".equals(map.get("multi"))) {
            excelExportVo1.setCommoditySku("一单多件");
        }
        excelExportVo1.setProductName(TimeUtils.getCurrentDateFormat("MM/dd"));
        DicBusinessItemDo dicBusinessItemDo = dicBusinessItemDao.selectById(map.get("trackId"));
        if (dicBusinessItemDo != null)
            excelExportVo1.setProductName(excelExportVo1.getProductName() + " " + dicBusinessItemDo.getDicItemValue());


        redisTemplate.opsForValue().set(ORDER_SKU_SUBTOTAL_CODE_KEY + TimeUtils.getCurrentDateFormat("MMdd"), todayCount + 1, 3, TimeUnit.DAYS);
        OrderOutputSkuSubtotalDo subtotalDo = new OrderOutputSkuSubtotalDo();
        subtotalDo.setCreateTime(new Date());
        subtotalDo.setCreateBy(currentUserId);
        if (StringUtils.isNotBlank(map.get("storageId"))) subtotalDo.setStorageId(Long.parseLong(map.get("storageId")));
        if (StringUtils.isNotBlank(map.get("trackId"))) subtotalDo.setTrackId(Long.parseLong(map.get("trackId")));
        if ("1".equals(map.get("multi"))) {
            subtotalDo.setType(0);
        } else if ("2".equals(map.get("multi"))) {
            subtotalDo.setType(1);
        }
        subtotalDo.setOrderNo("XJ" + TimeUtils.getCurrentDateFormat("MMddHHmm") + "-" + (todayCount + 1));
        subtotalDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        subTotalDao.insert(subtotalDo);
        List<OrderOutputSkuSumExcelExportVo> skuSumExcelExportVos = new ArrayList<>();
        List<OrderOutputProductDo> productDoList = productDao.selectSkuAndCountListByOrderIds(orderIdsList);
        if (productDoList == null) {
            throw new BizException(SysConstant.No_Data);
        }
        int[] total = new int[1];
        skuSumExcelExportVos = productDoList.stream().map(orderOutputProductDo -> {
            ProductInfoDo productInfoDo = productInfoDao.selectById(orderOutputProductDo.getProductId());
            OrderOutputSkuSumExcelExportVo excelExportVo = new OrderOutputSkuSumExcelExportVo();
            if (productInfoDo != null) {
                excelExportVo.setCommoditySku(productInfoDo.getCommoditySku());
                excelExportVo.setStorageSku(productInfoDo.getStorageSku());
                excelExportVo.setProductName(productInfoDo.getProductName());
                excelExportVo.setTotalCount(orderOutputProductDo.getCount() + "");
                total[0] = total[0] + orderOutputProductDo.getCount();
            }
            return excelExportVo;
        }).sorted(new Comparator<OrderOutputSkuSumExcelExportVo>() {
            @Override
            public int compare(OrderOutputSkuSumExcelExportVo o1, OrderOutputSkuSumExcelExportVo o2) {
                if (StringUtils.isBlank(o1.getCommoditySku())) return -1;
                if (StringUtils.isBlank(o2.getCommoditySku())) return 1;
                return o1.getCommoditySku().toUpperCase(Locale.ROOT).compareTo(o2.getCommoditySku().toUpperCase(Locale.ROOT));
            }
        }).collect(Collectors.toList());
        excelExportVo1.setTotalCount(total[0] + "");

        ImageEntity imageEntity = new ImageEntity();
        imageEntity.setUrl(BarCodeUtils.createCodeImage(subtotalDo.getOrderNo(), filePathTemp, subtotalDo.getOrderNo() + ".png"));
        imageEntity.setColspan(1);
        imageEntity.setRowspan(1);
        // 获取模板文件路径
        TemplateExportParams params = new TemplateExportParams(templatePath + "SKU-SUBTOTAL-NEW.xls");
        //设置sheetName，若不设置该参数，则使用得原本得sheet名称
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("order", excelExportVo1);
        data.put("image", imageEntity);
        data.put("list", skuSumExcelExportVos);
        // 获取workbook
        Workbook workbook = ExcelExportUtil.exportExcel(params, data);
        try {
            ExcelUtils.downLoadExcel(TimeUtils.getCurrentDateFormat() + "出荷依頼SKU小计.xls", response, workbook);
        } catch (IOException e) {
            e.printStackTrace();
        }
        updateOrderCheckStatus(ids, DicBusinessItemConstant.outCreateCheckState, currentUserId);
    }

    @Override
    public void exportPickExcel(Map<String, String> map, List<Long> ids, HttpServletResponse response) {
        if (ids == null) ids = new ArrayList<>();
        final List<Long> orderIdsList = ids;
        List<OrderOutputDo> orderList;
        List<OrderOutputPickupExportVo> orderOutputPickupExportVos = new ArrayList<>();
        if (orderIdsList.size() < 1) {
            orderList = dao.selectList1(map);
        } else {
            orderList = this.baseMapper.selectBatchIds(orderIdsList);
        }
        if (orderList == null) {
            throw new BizException(SysConstant.No_Data);
        }
        orderList.stream().sorted(new Comparator<OrderOutputDo>() {
            @Override
            public int compare(OrderOutputDo o1, OrderOutputDo o2) {
                if (o1.getCommoditySku() == null || o2.getCommoditySku() == null) return 1;
                return o1.getCommoditySku().compareToIgnoreCase(o2.getCommoditySku());
            }
        }).forEach(orderOutputDo -> {
            LambdaQueryWrapper<OrderOutputPackageDo> wrapper = new LambdaQueryWrapper();
            wrapper.eq(OrderOutputPackageDo::getOrderOutputId, orderOutputDo.getId());
            List<OrderOutputPackageDo> packageDoList = packageDao.selectList(wrapper);
            if (packageDoList != null && packageDoList.size() > 0) {
                packageDoList.stream().forEach(packageDo -> {
                    OrderOutputPickupExportVo pickupExportVo = new OrderOutputPickupExportVo();
                    pickupExportVo.setOrderNo(orderOutputDo.getOrderNo());
                    pickupExportVo.setOrderOutputNumber(orderOutputDo.getOrderOutputNumber());
                    pickupExportVo.setReceiverName(orderOutputDo.getReceiverName());
                    pickupExportVo.setTelPhone(orderOutputDo.getTelPhone());
                    if (StringUtils.isNotBlank(orderOutputDo.getTips())) {
                        if (orderOutputDo.getTips().length() > 30)
                            pickupExportVo.setTips(orderOutputDo.getTips().substring(0, 30));
                        else pickupExportVo.setTips(orderOutputDo.getTips());
                    }
                    pickupExportVo.setTrackNumber(orderOutputDo.getTrackNumber());
                    pickupExportVo.setDate(TimeUtils.getCurrentDateFormat());
                    DicBusinessItemDo itemDo = dicBusinessItemDao.selectById(orderOutputDo.getTrackId());
                    if (itemDo != null) pickupExportVo.setTrackName(itemDo.getDicItemValue());
                    StorageDo storageDo = storageDao.selectById(orderOutputDo.getStorageId());
                    if (storageDo != null) pickupExportVo.setStorageName(storageDo.getCode());
                    LambdaQueryWrapper<OrderOutputProductDo> wrapper1 = new LambdaQueryWrapper();
                    wrapper1.eq(OrderOutputProductDo::getPackageId, packageDo.getId());
                    List<OrderOutputProductDo> productDoList = productDao.selectList(wrapper1);
                    List<OrderOutputPickupProductExportVo> productExportVoList = new ArrayList<>();
                    if (productDoList != null && productDoList.size() > 0) {
                        productDoList.stream().forEach(orderOutputProductDo -> {
                            OrderOutputPickupProductExportVo productExportVo = new OrderOutputPickupProductExportVo();
                            ProductInfoDo productInfoDo = productInfoDao.selectById(orderOutputProductDo.getProductId());
                            productExportVo.setCommoditySku(productInfoDo.getCommoditySku());
                            if (productInfoDo.getProductName().length() > 15) {
                                productExportVo.setProductName(productInfoDo.getProductName().substring(0, 15));
                            } else {
                                productExportVo.setProductName(productInfoDo.getProductName());
                            }
                            productExportVo.setStorageSku(productInfoDo.getStorageSku());
                            productExportVo.setCount(orderOutputProductDo.getCount());
                            productExportVoList.add(productExportVo);
                        });
                    }
                    pickupExportVo.setProductList(productExportVoList);
                    orderOutputPickupExportVos.add(pickupExportVo);
                });
            }
        });
        Map<String, Object> objectMap = new HashMap<>();
        objectMap.put("list", orderOutputPickupExportVos);
        try {
            FreeMarkerUtils.downLoadWordTemp(response, templatePath, "pickup_temp3.ftl", TimeUtils.getCurrentDateFormat() + "拣货单.docx", objectMap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Long getProductId(String sellerSku, Long companyId) {
        Long productId = this.getProductId(sellerSku, companyId, 1);
        return productId;
    }


    @Override
    public Long getProductId(String sellerSku, Long companyId, int type) {
        sellerSku.trim().replaceAll("\\n", "").replaceAll("　", "");
        LambdaQueryWrapper<ProductInfoDo> productWrapper = new LambdaQueryWrapper();
        productWrapper.eq(ProductInfoDo::getCompanyId, companyId);
        productWrapper.and(product -> {
            product.eq(ProductInfoDo::getCommoditySku, sellerSku).or().eq(ProductInfoDo::getStorageSku, sellerSku);
        });
        ProductInfoDo productInfoDo = productInfoDao.selectOne(productWrapper);
        if (productInfoDo == null) {
            QueryWrapper skuWrapper = new QueryWrapper();
            skuWrapper.eq("sub_sku", sellerSku);
            skuWrapper.eq("company_id", companyId);
            ProductSkuMapDo productSkuMapDo = productSkuMapDao.selectOne(skuWrapper);
            if (productSkuMapDo == null) {
                if (type == 1) {
                    throw new BizException(SysConstant.Product_NotExist_Sku, sellerSku);
                } else {
                    return null;
                }
            }
            return productSkuMapDo.getProductInfoId();
        } else {
            return productInfoDo.getId();
        }
    }

    private ProductInfoDo getProductInfo(String sellerSku, Long companyId) {
        QueryWrapper productWrapper = new QueryWrapper();
        productWrapper.eq("commodity_sku", sellerSku);
        productWrapper.eq("company_id", companyId);
        ProductInfoDo productInfoDo = productInfoDao.selectOne(productWrapper);
        if (productInfoDo == null) {
            QueryWrapper skuWrapper = new QueryWrapper();
            skuWrapper.eq("sub_sku", sellerSku);
            skuWrapper.eq("company_id", companyId);
            ProductSkuMapDo productSkuMapDo = productSkuMapDao.selectOne(skuWrapper);
            if (productSkuMapDo == null) {
                throw new BizException(SysConstant.Product_NotExist_Sku, sellerSku);
            }
            return productInfoDao.selectById(productSkuMapDo.getProductInfoId());
        } else {
            return productInfoDo;
        }
    }

    @Override
    public void getExpressStatus(String status) {
        OkHttpClient.Builder client = OkHttpUtils.getUnsafeOkHttpClient().newBuilder();
        client.connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(true);
        int pageIndex = 0;
        int pageSize = 1000;
        int total = 0;
        try {
            do {
                pageIndex = pageIndex + 1;
                Request request = new Request.Builder().addHeader("Tracking-Api-Key", "df55f163-fd3a-44c9-8971-93ef327fbc37")
//                    .addHeader("Content-MD5", computeContentMD5Header(new ByteArrayInputStream(params.getBytes())))
                        .get().url("http://api.51tracking.com/v2/trackings/get?" + "page=" + pageIndex + "&limit=" + pageSize + "&lang=ja&archived=false&updated_date_min=" + TimeUtils.parseDate(TimeUtils.getCurrentDateFormat(-60)).getTime() / 1000 + "&status=" + status).build();
                Response response = null;
                String body = "";
                response = client.build().newCall(request).execute();
                body = response.body().string();
                log.debug(body);
                total = JSONObject.parseObject(body).getJSONObject("data").getInteger("total");
                int page = JSONObject.parseObject(body).getJSONObject("data").getInteger("page");
                JSONArray jsonArray = JSONObject.parseObject(body).getJSONObject("data").getJSONArray("items");
                List<TrackInfoDo> trackInfoDos = JSONObject.parseArray(jsonArray.toJSONString(), TrackInfoDo.class);
                trackInfoDos = trackInfoDos.stream().filter(trackInfoDo -> StringUtils.isNotBlank(trackInfoDo.getTrackingNumber())).collect(Collectors.toList());
                Map<Long, List<String>> map = new HashMap<>();
                Map<Long, List<StringAndDate>> mapDelivered = new HashMap<>();
                for (TrackInfoDo trackData : trackInfoDos) {
                    TrackInfoDo byId = mTrackService.getById(trackData.getTrackingNumber());
                    if (byId == null) {
                        mTrackService.save(trackData);
                    } else if (byId.getLastUpdateTime().getTime() - trackData.getLastUpdateTime().getTime() != 0) {
                        mTrackService.updateById(trackData);
                    } else {
                        continue;
                    }
                    if ("pending".equals(trackData.getStatus())) {

                    } else if ("transit".equals(trackData.getStatus())) {//运输中
                        if (!map.containsKey(DicBusinessItemConstant.outTraning)) {
                            map.put(DicBusinessItemConstant.outTraning, new ArrayList<>());
                        }
                        map.get(DicBusinessItemConstant.outTraning).add(trackData.getTrackingNumber());
                    } else if ("pickup".equals(trackData.getStatus())) {//配达中
                        if (!map.containsKey(DicBusinessItemConstant.outPickup)) {
                            map.put(DicBusinessItemConstant.outPickup, new ArrayList<>());
                        }
                        map.get(DicBusinessItemConstant.outPickup).add(trackData.getTrackingNumber());
                    } else if ("delivered".equals(trackData.getStatus())) {
                        if (!mapDelivered.containsKey(DicBusinessItemConstant.outDelivered)) {
                            mapDelivered.put(DicBusinessItemConstant.outDelivered, new ArrayList<>());
                        }
                        mapDelivered.get(DicBusinessItemConstant.outDelivered).add(new StringAndDate(trackData.getTrackingNumber(), trackData.getLastUpdateTime()));
                    } else if ("undelivered".equals(trackData.getStatus()) || "exception".equals(trackData.getStatus())) {
                        if (trackData.getLastEvent() != null && trackData.getLastEvent().contains("ご不在")) {
                            if (!map.containsKey(DicBusinessItemConstant.outTraning)) {
                                map.put(DicBusinessItemConstant.outTraning, new ArrayList<>());
                            }
                            map.get(DicBusinessItemConstant.outTraning).add(trackData.getTrackingNumber());
                        } else {
                            if (!map.containsKey(DicBusinessItemConstant.outException)) {
                                map.put(DicBusinessItemConstant.outException, new ArrayList<>());
                            }
                            map.get(DicBusinessItemConstant.outException).add(trackData.getTrackingNumber());
                        }
                    }
                }
                for (Map.Entry<Long, List<String>> entry : map.entrySet()) {
                    if (entry.getValue() == null || entry.getValue().size() < 1) continue;
                    List<Object> ids = dao.selectObjs(new LambdaQueryWrapper<OrderOutputDo>().in(OrderOutputDo::getTrackNumber, entry.getValue()).ge(OrderOutputDo::getSendDate, TimeUtils.getCurrentDateFormat(-90)).select(OrderOutputDo::getId));
                    update(new LambdaUpdateWrapper<OrderOutputDo>().set(OrderOutputDo::getStatus, entry.getKey()).in(OrderOutputDo::getId, ids));
//                    baseMapper.updateTrackStatus(entry.getKey().intValue(),ids);

                }
                for (Map.Entry<Long, List<StringAndDate>> entry : mapDelivered.entrySet()) {
                    if (entry.getValue() == null || entry.getValue().size() < 1) continue;
                    for (StringAndDate stringAndDate : entry.getValue()) {
                        List<Object> ids = dao.selectObjs(new LambdaQueryWrapper<OrderOutputDo>().eq(OrderOutputDo::getTrackNumber, stringAndDate.getString()).ge(OrderOutputDo::getSendDate, TimeUtils.getCurrentDateFormat(-90)).select(OrderOutputDo::getId));
                        if (ids == null) continue;
                        if (ids.size() == 0) continue;
                        if (ids.size() == 1) {
                            update(new LambdaUpdateWrapper<OrderOutputDo>().set(OrderOutputDo::getArriveTime, stringAndDate.getDate()).set(OrderOutputDo::getStatus, entry.getKey()).eq(OrderOutputDo::getId, ids.get(0)));
                        } else {
                            update(new LambdaUpdateWrapper<OrderOutputDo>().set(OrderOutputDo::getArriveTime, stringAndDate.getDate()).set(OrderOutputDo::getStatus, entry.getKey()).in(OrderOutputDo::getId, ids));
                        }
//                    baseMapper.updateTrackStatus(entry.getKey().intValue(),ids);
                    }
                }
            } while ((total - pageSize * pageIndex) > 0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postExpress2Api() {
        List<OrderOutputDo> sendOutEntities = baseMapper.selectPostExpress2ApiList(TimeUtils.getCurrentDateFormat(-7), TimeUtils.getCurrentDateTimeFormat());
        for (int i = 0; i <= sendOutEntities.size() / 40; i++) {
            List<Map> mapList = new ArrayList<>();
            int end = 0;
            if (i == sendOutEntities.size() / 40) {
                end = sendOutEntities.size();
            } else {
                end = (i + 1) * 40;
            }
            for (OrderOutputDo entity : sendOutEntities.subList(i * 40, end)) {
                Map map = new HashMap();
                map.put("tracking_number", entity.getTrackNumber());
                if (entity.getTrackId() == DicBusinessItemConstant.sagawaExpress) {
                    map.put("carrier_code", "sagawa");
                } else if (entity.getTrackId() == DicBusinessItemConstant.yamatoExpress || entity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressNew) || entity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox) || entity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressSmall)) {
                    map.put("carrier_code", "taqbin-jp");
                } else if (entity.getTrackId() == DicBusinessItemConstant.jpostExpress || entity.getTrackId() == DicBusinessItemConstant.jpostExpressCom || entity.getTrackId() == DicBusinessItemConstant.jpostExpressCod) {
                    map.put("carrier_code", "japan-post");
                } else if (entity.getTrackId() == DicBusinessItemConstant.xinongExpress) {
                    map.put("carrier_code", "seino");
                }
                mapList.add(map);
            }
            OkHttpClient.Builder client = OkHttpUtils.getUnsafeOkHttpClient().newBuilder();
            client.connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                    .retryOnConnectionFailure(true);
            Request request = new Request.Builder().addHeader("Tracking-Api-Key", "df55f163-fd3a-44c9-8971-93ef327fbc37")
//                    .addHeader("Content-MD5", computeContentMD5Header(new ByteArrayInputStream(params.getBytes())))
                    .post(RequestBody.create(MediaType.get("text/xml"), JSONObject.toJSON(mapList).toString())).url("https://api.51tracking.com/v2/trackings/batch").build();
            Response response = null;
            String body = "";
            try {
                response = client.build().newCall(request).execute();
                body = response.body().string();
                System.out.println(body);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void updateArchivedExpressCode() {
        LambdaQueryWrapper<TrackInfoDo> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TrackInfoDo::getArchived, 0).eq(TrackInfoDo::getStatus, "delivered").gt(TrackInfoDo::getLastUpdateTime, TimeUtils.getCurrentDateFormat(-30));
        List<TrackInfoDo> trackDataList = mTrackDao.selectList(wrapper);
        for (int i = 0; i <= trackDataList.size() / 40; i++) {
            int end = 0;
            if (i == trackDataList.size() / 40) {
                end = trackDataList.size();
            } else {
                end = (i + 1) * 40;
            }
            List<Map> mapList = new ArrayList<>();
            for (TrackInfoDo entity : trackDataList.subList(i * 40, end)) {
                Map map = new HashMap();
                map.put("tracking_number", entity.getTrackingNumber());
                map.put("carrier_code", entity.getCarrierCode());
                map.put("archived", "true");
                entity.setArchived(1);
                mapList.add(map);
                LambdaQueryWrapper<OrderOutputDo> orderOutputDoLambdaQueryWrapper = new LambdaQueryWrapper();
                if ("sagawa".equals(entity.getCarrierCode())) {
                    orderOutputDoLambdaQueryWrapper.eq(OrderOutputDo::getTrackId, DicBusinessItemConstant.sagawaExpress);
                    if ("taqbin-jp".equals(entity.getCarrierCode())) {
                        orderOutputDoLambdaQueryWrapper.in(OrderOutputDo::getTrackId, DicBusinessItemConstant.yamatoExpress, DicBusinessItemConstant.yamatoExpressNew, DicBusinessItemConstant.yamatoExpressBox, DicBusinessItemConstant.yamatoExpressSmall);
                        map.put("carrier_code", "");
                    } else if ("japan-post".equals(entity.getCarrierCode())) {
                        orderOutputDoLambdaQueryWrapper.in(OrderOutputDo::getTrackId, new long[]{DicBusinessItemConstant.jpostExpress, DicBusinessItemConstant.jpostExpressCom, DicBusinessItemConstant.jpostExpressCod});
                    }
                } else if ("seino".equals(entity.getCarrierCode())) {
                    orderOutputDoLambdaQueryWrapper.eq(OrderOutputDo::getTrackId, DicBusinessItemConstant.sagawaExpress);
                }
                orderOutputDoLambdaQueryWrapper.eq(OrderOutputDo::getTrackNumber, entity.getTrackingNumber()).lt(OrderOutputDo::getStatus, DicBusinessItemConstant.outDelivered).ge(OrderOutputDo::getStatus, DicBusinessItemConstant.outSendOut).ge(OrderOutputDo::getSendDate, TimeUtils.getCurrentDateFormat(-30));
                List<OrderOutputDo> orderOutputDos = dao.selectList(orderOutputDoLambdaQueryWrapper);
                if (orderOutputDos.size() > 0) {
                    orderOutputDos.stream().forEach(new Consumer<OrderOutputDo>() {
                        @Override
                        public void accept(OrderOutputDo orderOutputDo) {
                            LambdaUpdateWrapper<OrderOutputDo> orderOutputDoLambdaUpdateWrapper = new LambdaUpdateWrapper();
                            orderOutputDoLambdaUpdateWrapper.set(OrderOutputDo::getStatus, DicBusinessItemConstant.outDelivered).eq(OrderOutputDo::getId, orderOutputDo.getId());
                            update(orderOutputDoLambdaUpdateWrapper);
                        }
                    });


                }
            }
            OkHttpClient.Builder client = OkHttpUtils.getUnsafeOkHttpClient().newBuilder();
            client.connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                    .retryOnConnectionFailure(true);
            Request request = new Request.Builder().addHeader("Tracking-Api-Key", "df55f163-fd3a-44c9-8971-93ef327fbc37")
//                    .addHeader("Content-MD5", computeContentMD5Header(new ByteArrayInputStream(params.getBytes())))
                    .url("http://api.51tracking.com/v2/trackings/updatemore").post(RequestBody.create(MediaType.get("application/json"), JSONObject.toJSON(mapList).toString())).build();
            Response response = null;
            String body = "";
            try {
                response = client.build().newCall(request).execute();
                body = response.body().string();
                System.out.println(body);
                if (JSONObject.parseObject(body).getJSONObject("meta").getIntValue("code") == 200) {
                    mTrackService.updateBatchById(trackDataList.subList(i * 40, end));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void autoUploadNoYetExpressNumber() {
        List<String> orderids = new ArrayList<>();
        List<ShopDo> shopBeans = shopService.list();
        for (ShopDo shop : shopBeans) {
            if (shop.getRakutenLicense() != null) {
                orderids.addAll(orderRakutenDao.queryByShopIdAndNoUploadExpress(shop.getId(), TimeUtils.getCurrentDateFormat(-25), TimeUtils.getCurrentDateFormat(+1)));
            }
            if (shop.getAmazonSellerId() != null) {
                orderids.addAll(orderAmazonDao.queryByShopIdAndNoUploadExpress(shop.getId(), TimeUtils.getCurrentDateFormat(-25), TimeUtils.getCurrentDateFormat(+1)));
            }
            if (shop.getShopifyToken() != null) {
                orderids.addAll(shopifyDao.queryByShopIdAndNoUploadExpress(shop.getId(), TimeUtils.getCurrentDateFormat(-25), TimeUtils.getCurrentDateFormat(+1)));
            }
            if (shop.getYahooRefreshToken() != null) {
                orderids.addAll(yahooService.queryByShopIdAndNoUploadExpress(shop.getId(), TimeUtils.getCurrentDateFormat(-25), TimeUtils.getCurrentDateFormat(+1)));
            }
            if (shop.getQootenId() != null) {
                orderids.addAll(orderQoo10Sercie.queryByShopIdAndNoUploadExpress(shop.getId(), TimeUtils.getCurrentDateFormat(-25), TimeUtils.getCurrentDateFormat(+1)));
            }
//            if (shop.getYahooRefreshToken() != null) {
            orderids.addAll(ecangService.queryByShopIdAndNoUploadExpress(shop.getId(), TimeUtils.getCurrentDateFormat(-25), TimeUtils.getCurrentDateFormat(+1)));
//            }
        }
        if (orderids != null && orderids.size() > 0)
            //TODO 处理orderids
            autoUploadExpressNumber(orderids);
    }

    @Override
    public void autoUploadLasHourExpressNumber() {
//        List<String> orderNumbers = baseMapper.selectLastHourOrder(TimeUtils.formatDate(new Date(System.currentTimeMillis() - 40 * 60 * 1000), TimeUtils.YYYYMMddHHmmss), TimeUtils.getCurrentDateTimeFormat());

        String startD = TimeUtils.formatDate(new Date(System.currentTimeMillis() - 43 * 60 * 1000), TimeUtils.YYYYMMddHHmmss);
        String startE = TimeUtils.formatDate(new Date(System.currentTimeMillis() - 13 * 60 * 1000), TimeUtils.YYYYMMddHHmmss);
        List<String> orderNumbers = new ArrayList<>();
        orderNumbers.addAll(baseMapper.selectLastHourOrder(startD, startE));
        orderNumbers.addAll(baseMapper.selectLastHourOrderC1370(startD, startE));
        autoUploadExpressNumber(orderNumbers);
    }

    @Override
    public void autoUploadLasHourExpressNumber1() {
        List<String> orderNumbers = baseMapper.selectLastHourOrder(TimeUtils.formatDate(new Date(System.currentTimeMillis() - 40 * 60 * 1000), TimeUtils.YYYYMMddHHmmss), TimeUtils.getCurrentDateTimeFormat());

//        List<String> orderNumbers = baseMapper.selectLastHourOrder(TimeUtils.formatDate(new Date(System.currentTimeMillis() - 43 * 60 * 1000),
//                TimeUtils.YYYYMMddHHmmss), TimeUtils.formatDate(new Date(System.currentTimeMillis() - 13 * 60 * 1000),
//                TimeUtils.YYYYMMddHHmmss));
        autoUploadExpressNumber(orderNumbers);
    }

    public void autoUploadExpressNumber(List<String> orderids) {
        threadPoolTaskExecutor.execute(() -> {
            //set去重
            Set<String> set = new HashSet<>();
            set.addAll(orderids);
            orderids.clear();
            List<String> orderidList = new ArrayList<>();
            orderidList.addAll(set);
            List<String> orderIdExist = new ArrayList<>();
            List<OrderFulfillment> fulfillmentOrderList = new ArrayList<>();
            Map<Long, List<OrderShippingModelRequest>> shopRakutenOrderMap = new HashMap<>();
            Map<Long, List<ShopifyRequestReq>> shopifyOrderMap = new HashMap<>();
            Map<Long, List<Qoo10RequestReq>> qoo10OrderMap = new HashMap<>();
            Map<Long, List<OrderFulfillment>> shopAmzonOrderMap = new HashMap<>();
            Map<Long, List<OrderShipStatusChangeReq>> yahooOrderMap = new HashMap<>();
            log.info("autoUploadExpressNumber :数据开始处理");
            for (String expressOrder : orderidList) {
                if (StringUtils.isEmpty(expressOrder)) continue;
                String orderNumber = expressOrder.trim();
                LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper();
                OrderOutputDo sendOutEntity;
                if (orderNumber.startsWith("OT")) {
                    sendOutEntity = baseMapper.selectById(orderNumber.substring(10));
                } else {
                    wrapper.eq(OrderOutputDo::getOrderNo, orderNumber);
                    wrapper.last("limit 1");
                    sendOutEntity = baseMapper.selectOne(wrapper);
                }
                if (sendOutEntity == null) continue;
                //非已发货状态的订单不自动上传单号
                if (sendOutEntity.getStatus() <= DicBusinessItemConstant.outWaitSendOut || sendOutEntity.getStatus() >= DicBusinessItemConstant.orderCutOff)
                    continue;
                if (sendOutEntity.getPlatform() != null && "qianyi".equals(sendOutEntity.getPlatform())) {
                    //千易erp推送订单
                    dealwithQianyiOrder(sendOutEntity);
                }
                if (sendOutEntity.getPlatform() != null && "ecang".equals(sendOutEntity.getPlatform())) {
                    //易仓erp推送订单
                    dealwithEcangOrder(sendOutEntity);
                    continue;
                }
                if (sendOutEntity.getPlatform() != null && "qoo10".equals(sendOutEntity.getPlatform())) {
                    //易仓erp推送订单
                    Qoo10RequestReq req = new Qoo10RequestReq(sendOutEntity.getPlatformNumber(), getTrackCode(sendOutEntity.getTrackId()), sendOutEntity.getTrackNumber());
                    if (qoo10OrderMap.get(sendOutEntity.getShopId()) == null) {
                        qoo10OrderMap.put(sendOutEntity.getShopId(), new ArrayList<>());
                    }
                    qoo10OrderMap.get(sendOutEntity.getShopId()).add(req);
                    continue;
                }
                if (org.springframework.util.StringUtils.isEmpty(sendOutEntity.getTrackNumber())) {//发货仓库为CKT时，不自动上传
                    continue;
                }

                //组装shopify订单数据
                if (sendOutEntity.getOrderNo().contains("shopify") || (sendOutEntity.getOrderNo().startsWith("#AFT"))) {
                    //例如shopify_123456 截取下划线后的 和t_order_shopify表关联取订单号
                    String orderNo = sendOutEntity.getOrderNo().substring(8);
                    if (orderNo.length() < 4) {
                        orderNo = sendOutEntity.getOrderNo().substring(4);
                    }
                    long orderId = 0;
                    try {
                        orderId = Long.parseLong(orderNo);
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                        continue;
                    }
                    OrderShopifyDo shopifyDo = shopifyDao.selectOne(new QueryWrapper<OrderShopifyDo>().eq("order_number", orderId).eq("shop_id", sendOutEntity.getShopId()));
                    String urlString = new String();
//                    urlList.add("www.baidu.com");
                    if (shopifyDo == null) {
                        shopifyDo = shopifyDao.selectById(sendOutEntity.getPlatformNumber());
                    }
                    if (shopifyDo != null) {
                        LambdaQueryWrapper<OrderOutputPackageDetailDo> outPackageDetailWrappr = new LambdaQueryWrapper<>();
                        outPackageDetailWrappr.eq(OrderOutputPackageDetailDo::getOrderOutputId, sendOutEntity.getId());
                        List<OrderOutputPackageDetailDo> orderPackageDetailList = packageDetailDao.selectList(outPackageDetailWrappr);
                        if (orderPackageDetailList.size() < 1) {
                            OrderOutputPackageDetailDo detailDo = new OrderOutputPackageDetailDo();
                            detailDo.setTrackNumber(sendOutEntity.getTrackNumber());
                            orderPackageDetailList.add(detailDo);
                        }
                        for (OrderOutputPackageDetailDo detailDo : orderPackageDetailList) {
                            ShopifyRequestReq shopifyRequestReq = new ShopifyRequestReq();
//                        params.setLocation_id(shopifyDo.getLocationId());
                            shopifyRequestReq.setOrderOutputId(sendOutEntity.getId());
                            shopifyRequestReq.setPackageDetailId(detailDo.getId());
                            shopifyRequestReq.setOrderId(shopifyDo.getOrderId());
                            String trackNumber = StringUtils.isNotBlank(detailDo.getTrackNumber()) ? detailDo.getTrackNumber() : sendOutEntity.getTrackNumber();
                            shopifyRequestReq.setNumber(trackNumber);
                            if (sendOutEntity.getTrackId() == DicBusinessItemConstant.sagawaExpress) {
                                shopifyRequestReq.setCompany("Sagawa");
                                urlString = ("https://k2k.sagawa-exp.co.jp/p/web/okurijosearch.do?okurijoNo=" + trackNumber);
                            } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.yamatoExpress || sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressNew) || sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox) || sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressSmall)) {
                                shopifyRequestReq.setCompany("Yamato");
                                urlString = ("https://jizen.kuronekoyamato.co.jp/jizen/servlet/crjz.b.NQ0010?id=" + trackNumber);
                            } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpress || sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCom || sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCod) {
                                shopifyRequestReq.setCompany("Japan Post");
                                urlString = ("https://trackings.post.japanpost.jp/services/srv/search/direct?reqCodeNo1=" + trackNumber);
                            } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.xinongExpress) {
                                shopifyRequestReq.setCompany("西濃運輸");
                                urlString = ("https://track.seino.co.jp/kamotsu/GempyoNoShokai.do?action=Inquiry&GNPNO1=" + trackNumber);
                            }
//                        List<ShopifyRequestReq> shopifyItemList = new ArrayList<>();

                            shopifyRequestReq.setUrl(urlString);

//                        shopifyItemList.add(shopifyRequestReq);
                            if (shopifyOrderMap.get(shopifyDo.getShopId()) == null) {
                                shopifyOrderMap.put(shopifyDo.getShopId(), new ArrayList<>());
                            }
                            shopifyOrderMap.get(shopifyDo.getShopId()).add(shopifyRequestReq);
                        }
                    }
                    continue;
                }

                if (orderIdExist.contains(sendOutEntity.getOrderNo())) continue;
                orderIdExist.add(sendOutEntity.getOrderNo());
                OrderShippingModelRequest orderShippingModel = new OrderShippingModelRequest();
                LambdaQueryWrapper<OrderRakutenDo> rakutenWrapper = new LambdaQueryWrapper<>();
                rakutenWrapper.eq(OrderRakutenDo::getOrderNumber, sendOutEntity.getOrderNo()).eq(OrderRakutenDo::getShopId, sendOutEntity.getShopId()).last("limit 1");
                OrderRakutenDo rakutenOrder = orderRakutenDao.selectOne(rakutenWrapper);
                if (rakutenOrder == null) {//Amazon or Yahoo 订单处理
                    LambdaQueryWrapper<OrderYahooDo> yahooWRapper = new LambdaQueryWrapper<>();
                    yahooWRapper.eq(OrderYahooDo::getOrderId, sendOutEntity.getOrderNo()).eq(OrderYahooDo::getShopId, sendOutEntity.getShopId()).last("limit 1");
                    OrderYahooDo orderYahooDo = yahooService.getOne(yahooWRapper);
                    if (orderYahooDo == null) {
                        List<OrderFulfillment> fulfillments = mOrderAmazonService.dealWithAmazonOrder(sendOutEntity);
                        if (fulfillments != null) {
                            if (shopAmzonOrderMap.get(sendOutEntity.getShopId()) == null) {
                                shopAmzonOrderMap.put(sendOutEntity.getShopId(), new ArrayList<OrderFulfillment>() {
                                });
                            }
                            shopAmzonOrderMap.get(sendOutEntity.getShopId()).addAll(fulfillments);
                        }
                        continue;
                    } else {
                        OrderShipStatusChangeReq fulfillment = buidWithYahooOrder(orderYahooDo, sendOutEntity);
                        if (fulfillment != null) {
                            if (yahooOrderMap.get(sendOutEntity.getShopId()) == null) {
                                yahooOrderMap.put(sendOutEntity.getShopId(), new ArrayList<>());
                            }
                            yahooOrderMap.get(sendOutEntity.getShopId()).add(fulfillment);
                        }
                        continue;
                    }
                }
                if (rakutenOrder.getShopId().intValue() != sendOutEntity.getShopId().intValue()) {
                    if (rakutenOrder.getShopId() == 4 && sendOutEntity.getOrderNo().startsWith("369266")) {
                        sendOutEntity.setShopId(4L);
                    } else if (sendOutEntity.getOrderNo().startsWith("382110")) {
                        sendOutEntity.setShopId(106L);
                    } else {
                        continue;
                    }
                }

                orderShippingModel.setOrderNumber(sendOutEntity.getOrderNo().trim());
                List<BasketidModelRequest> basketidModelRequests = new ArrayList<>();
                BasketidModelRequest basketidModelRequest = new BasketidModelRequest();

                List<ShippingModelEntity> shippingModelRequestList = new ArrayList<>();
                //根据平台订单号去发货单模糊查找记录获取运单号
                LambdaQueryWrapper<OrderOutputDo> orderOutputDoWrapper = new LambdaQueryWrapper();
                orderOutputDoWrapper.eq(OrderOutputDo::getOrderNo, sendOutEntity.getOrderNo());
                orderOutputDoWrapper.eq(OrderOutputDo::getPlatform, "rakuten");
                orderOutputDoWrapper.gt(OrderOutputDo::getSendDate, TimeUtils.getCurrentDateFormat(-90));
                orderOutputDoWrapper.eq(OrderOutputDo::getCompanyId, sendOutEntity.getCompanyId());
                List<OrderOutputDo> sendOutEntityList = baseMapper.selectList(orderOutputDoWrapper);
                LambdaQueryWrapper<OrderRakutenPackageDo> rakutenPackageWrapper = new LambdaQueryWrapper();
                rakutenPackageWrapper.eq(OrderRakutenPackageDo::getOrderId, rakutenOrder.getId());
                List<OrderRakutenPackageDo> packageDoList = rakutenPackageDao.selectList(rakutenPackageWrapper);
                if (packageDoList == null || packageDoList.size() < 1) continue;
                LambdaQueryWrapper<OrderRakutenProductDo> rakutenProductWrapper = new LambdaQueryWrapper();
                rakutenProductWrapper.eq(OrderRakutenProductDo::getBasketId, packageDoList.get(0).getBasketId());
                List<OrderRakutenProductDo> productDoList = rakutenProductDao.selectList(rakutenProductWrapper);
                if (productDoList == null || productDoList.size() < 1) continue;
                //先判断一个订单多个商品
                if (productDoList.size() > 1 || productDoList.get(0).getUnits() > 1) {
                    //遍历乐天订单的商品
                    item:
                    for (OrderOutputDo sendEntity : sendOutEntityList) {
                        String updateDate = TimeUtils.getCurrentDateFormat();
                        try {
                            updateDate = TimeUtils.formatDate(sendEntity.getSendTime()).split(" ")[0];
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        String deliveryCompanyCode = "1000";
                        if (sendEntity.getTrackId() == DicBusinessItemConstant.sagawaExpress) {
                            deliveryCompanyCode = "1002";
                        } else if (sendEntity.getTrackId() == DicBusinessItemConstant.yamatoExpress || sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressNew) || sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox) || sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressSmall)) {
                            deliveryCompanyCode = "1001";
                        } else if (sendEntity.getTrackId() == DicBusinessItemConstant.jpostExpress || sendEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCom || sendEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCod) {
                            deliveryCompanyCode = "1003";
                        } else if (sendEntity.getTrackId() == DicBusinessItemConstant.xinongExpress) {
                            deliveryCompanyCode = "1004";
                        }
                        LambdaQueryWrapper<OrderOutputPackageDetailDo> outPackageDetailWrappr = new LambdaQueryWrapper<>();
                        outPackageDetailWrappr.eq(OrderOutputPackageDetailDo::getOrderOutputId, sendEntity.getId());
                        List<OrderOutputPackageDetailDo> orderPackageDetailList = packageDetailDao.selectList(outPackageDetailWrappr);
                        if (org.springframework.util.StringUtils.isEmpty(sendEntity.getTrackNumber()) && orderPackageDetailList.size() < 1)
                            break;
//                    //判断两个商品是否一致
//                    ProductInfoDo productInfoDo = getProductInfo(rakutenProductInfo.getItemNumber(), sendOutEntity.getCompanyId());
//                    if (sendEntity.getCommoditySku().contains(",")) {
////                            if (productDoList.size() > 0 && i == 0) {
////                                shippingModelRequestList.add(new ShippingModelEntity(orderModel.getPackageModelList().get(0).getShippingModelList().get(0).getShippingDetailId(),
////                                        deliveryCompanyCode, sendEntity.getTrackNumber(), updateDate));
////                            } else {
//                        shippingModelRequestList.add(new ShippingModelEntity(deliveryCompanyCode, sendEntity.getTrackNumber(), updateDate));
////                            }
//                        break item;
//                    }
//
//                    if (productInfoDo == null) continue;
//                    if (commoditySku.contains(sendEntity.getCommoditySku())) {
//                            if (productDoList.size() > 0 && i == 0) {
//                                shippingModelRequestList.add(new ShippingModelEntity(orderModel.getPackageModelList().get(0).getShippingModelList().get(0).getShippingDetailId(),
//                                        deliveryCompanyCode, sendEntity.getTrackNumber(), updateDate));
//                            } else {
                        if (StringUtils.isBlank(updateDate)) updateDate = TimeUtils.getCurrentDateFormat();
                        if (orderPackageDetailList.size() > 1) {
                            Map<String, List<OrderOutputPackageDetailDo>> mapCollect = orderPackageDetailList.stream()
                                    .collect(Collectors.groupingBy(OrderOutputPackageDetailDo::getTrackNumber));
                            for (String trackNumber : mapCollect.keySet()) {
                                shippingModelRequestList.add(new ShippingModelEntity(deliveryCompanyCode, trackNumber, updateDate));
                            }
                        } else {
                            LambdaQueryWrapper<OrderRakutenShippingDo> wrapper1 = new LambdaQueryWrapper();
                            wrapper1.eq(OrderRakutenShippingDo::getPackageId, productDoList.get(0).getBasketId());
                            List<OrderRakutenShippingDo> orderRakutenShippingDos = rakutenShippingDao.selectList(wrapper1);
                            if (orderRakutenShippingDos != null && orderRakutenShippingDos.size() > 0 && orderRakutenShippingDos.get(0).getShippingNumber() == null) {//已经上传了null单号的情况
                                shippingModelRequestList.add(new ShippingModelEntity(orderRakutenShippingDos.get(0).getShippingDetailId(), deliveryCompanyCode, sendOutEntity.getTrackNumber(), updateDate));
                            } else if (orderRakutenShippingDos != null && orderRakutenShippingDos.size() > 0) {
                                for (OrderRakutenShippingDo orderRakutenShippingDo : orderRakutenShippingDos) {
                                    if (orderRakutenShippingDo.getShippingNumber() != null && orderRakutenShippingDo.getShippingNumber().equals(sendEntity.getTrackNumber())) {
                                        continue item;
                                    }
                                }
                                shippingModelRequestList.add(new ShippingModelEntity(deliveryCompanyCode, sendEntity.getTrackNumber(), updateDate));
                            } else {
                                shippingModelRequestList.add(new ShippingModelEntity(deliveryCompanyCode, sendEntity.getTrackNumber(), updateDate));
                            }
                        }
//
                    }
                } else {
                    if (rakutenOrder.getIsUploadExpress() == 1) {
                        continue;
                    }
                    //一个商品，对应一个发货订单
                    String updateDate = TimeUtils.getCurrentDateFormat();
                    try {
                        updateDate = TimeUtils.formatDate(sendOutEntity.getUpdateTime()).split(" ")[0];
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    String deliveryCompanyCode = getShipCompanyCode2RakutenOrYahoo(sendOutEntity.getTrackId());

                    LambdaQueryWrapper<OrderRakutenShippingDo> wrapper1 = new LambdaQueryWrapper();
                    wrapper1.eq(OrderRakutenShippingDo::getPackageId, productDoList.get(0).getBasketId());
                    List<OrderRakutenShippingDo> orderRakutenShippingDos = rakutenShippingDao.selectList(wrapper1);

                    if (orderRakutenShippingDos != null && orderRakutenShippingDos.size() > 0 && !sendOutEntity.getCompanyId().equals(201) && !sendOutEntity.getCompanyId().equals(316)) {//已经上传了单号的情况
                        shippingModelRequestList.add(new ShippingModelEntity(orderRakutenShippingDos.get(0).getShippingDetailId(), deliveryCompanyCode, sendOutEntity.getTrackNumber(), updateDate));
                    } else {
                        shippingModelRequestList.add(new ShippingModelEntity(deliveryCompanyCode, sendOutEntity.getTrackNumber(), updateDate));
                    }
                }
                if (shippingModelRequestList.size() < 1) continue;
                basketidModelRequest.setShippingModelList(shippingModelRequestList);
                basketidModelRequest.setBasketId(productDoList.get(0).getBasketId());
                if (shopRakutenOrderMap.get(sendOutEntity.getShopId()) == null) {
                    shopRakutenOrderMap.put(sendOutEntity.getShopId(), new ArrayList<OrderShippingModelRequest>() {
                    });
                }
                basketidModelRequests.add(basketidModelRequest);
                orderShippingModel.setBasketidModelList(basketidModelRequests);
                shopRakutenOrderMap.get(sendOutEntity.getShopId()).add(orderShippingModel);
            }
            log.info("autoUploadExpressNumber：数据处理完成");
            log.info("autoUploadExpressNumber：开始分发平台上传");
            try {
                mOrderAmazonService.uploadExpressNo2Amazon(shopAmzonOrderMap);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("autoUploadExpressNumber", e);
            }
            log.info("autoUploadExpressNumber：Amazon平台上传完成");
            orderRakutenService.updateRakutenExpressNumberByOrderIds(shopRakutenOrderMap);
            log.info("autoUploadExpressNumber：Rakuten平台上传完成");
            //上传或修改shopify订单数据
            orderShopifyService.dealShopifyOrdersByIds(shopifyOrderMap);
            log.info("autoUploadExpressNumber：shopify平台上传完成");
            //上传或修改Qoo10订单数据
            orderQoo10Sercie.setSendingInfoByList(qoo10OrderMap);
            log.info("autoUploadExpressNumber：Qoo10平台上传完成");
            //上传或修改yahoo订单数据
            yahooService.orderShipStatusChange(yahooOrderMap);
            log.info("autoUploadExpressNumber：yahoo平台上传完成");
            log.info("autoUploadExpressNumber：全部平台上传完成");
        });
    }

    private void dealwithQoo10Order(List<Qoo10RequestReq> qoo10OrderMap, OrderOutputDo sendOutEntity) {
        Qoo10RequestReq req = new Qoo10RequestReq(sendOutEntity.getPlatformNumber(), getTrackCode(sendOutEntity.getTrackId()), sendOutEntity.getTrackNumber());
        qoo10OrderMap.add(req);
    }

    private String getShipCompanyCode2RakutenOrYahoo(Long trackId) {
        if (trackId == DicBusinessItemConstant.sagawaExpress) {
            return "1002";
        } else if (trackId == DicBusinessItemConstant.yamatoExpress || trackId.equals(DicBusinessItemConstant.yamatoExpressNew) || trackId.equals(DicBusinessItemConstant.yamatoExpressBox) || trackId.equals(DicBusinessItemConstant.yamatoExpressSmall)) {
            return "1001";
        } else if (trackId == DicBusinessItemConstant.jpostExpress || trackId == DicBusinessItemConstant.jpostExpressCom || trackId == DicBusinessItemConstant.jpostExpressCod) {
            return "1003";
        } else if (trackId == DicBusinessItemConstant.xinongExpress) {
            return "1004";
        }
        return "1000";
    }

    private OrderShipStatusChangeReq buidWithYahooOrder(OrderYahooDo orderYahooDo, OrderOutputDo sendOutEntity) {
        OrderShipStatusChangeReq req = new OrderShipStatusChangeReq();
        req.setOrderId(sendOutEntity.getOrderNo());
        req.setIsPointFix(true);
        req.setShopId(sendOutEntity.getShopId());
        req.setShipStatus("3");
        req.setShipCompanyCode(getShipCompanyCode2RakutenOrYahoo(sendOutEntity.getTrackId()));
        LambdaQueryWrapper<OrderOutputPackageDetailDo> outPackageDetailWrappr = new LambdaQueryWrapper<>();
        outPackageDetailWrappr.eq(OrderOutputPackageDetailDo::getOrderOutputId, sendOutEntity.getId());
        List<OrderOutputPackageDetailDo> orderPackageDetailList = packageDetailDao.selectList(outPackageDetailWrappr);
        if (orderPackageDetailList.size() <= 1) {
            req.setShipInvoiceNumber1(sendOutEntity.getTrackNumber());
        } else {
            req.setShipInvoiceNumber1(orderPackageDetailList.get(0).getTrackNumber());
            req.setShipInvoiceNumber1(orderPackageDetailList.get(1).getTrackNumber());
            if (orderPackageDetailList.size() > 2) {
                String trackNumberDetail = orderPackageDetailList.stream().map(OrderOutputPackageDetailDo::getTrackNumber).collect(Collectors.joining(","));
                req.setShipNotes(trackNumberDetail);
            }
        }
        req.setShipDate(TimeUtils.formatDate(sendOutEntity.getUpdateTime(), "yyyyMMdd"));
        return req;
    }

    private List<ShopifyShippingEneity> getShopifyFulfillmentData(OrderOutputDo sendOutEntity) {
        orderShopifyService.buildFulfillmentData(sendOutEntity);
        return new ArrayList<>();
    }

    private void dealwithQianyiOrder(OrderOutputDo sendOutEntity) {

    }

    private void dealwithEcangOrder(OrderOutputDo sendOutEntity) {
        log.info(String.format("易仓订单%s开始回传", sendOutEntity.getPlatformNumber()));
        String trackCode = getTrackCode(sendOutEntity.getTrackId());
        String smCode = getSmCode(sendOutEntity.getTrackId(), sendOutEntity.getCompanyId());
        boolean b = ecangService.uploadTrackingNo(sendOutEntity.getPlatformNumber(), sendOutEntity.getOrderNo(), sendOutEntity.getTrackNumber(), smCode, trackCode);
        LambdaUpdateWrapper<OrderEcangDo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(OrderEcangDo::getIsSendOut, 1);
        updateWrapper.set(OrderEcangDo::getIsUpload, 1);
        updateWrapper.set(OrderEcangDo::getSmCode, smCode);
        updateWrapper.set(OrderEcangDo::getTrackCode, trackCode);
        updateWrapper.set(OrderEcangDo::getTrackId, sendOutEntity.getTrackId());
        updateWrapper.set(OrderEcangDo::getTrackNumber, sendOutEntity.getTrackNumber());
        updateWrapper.eq(OrderEcangDo::getOrderCode, sendOutEntity.getPlatformNumber());
        ecangService.update(updateWrapper);
        try {
            Thread.sleep(1000 * 10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        boolean b1 = ecangService.orderStatusModify(sendOutEntity.getShopId(), sendOutEntity.getPlatformNumber(), 1, sendOutEntity.getTrackNumber(), sendOutEntity.getTrackId(), null, trackCode);
        if (b1) {
            updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(OrderEcangDo::getOrderStatus, 8);
            updateWrapper.eq(OrderEcangDo::getOrderCode, sendOutEntity.getPlatformNumber());
            ecangService.update(updateWrapper);
            log.info(String.format("易仓订单%s回传成功", sendOutEntity.getPlatformNumber()));
        } else {
            log.info(String.format("易仓订单%s回传失败", sendOutEntity.getPlatformNumber()));
        }
//        boolean b1 = ecangService.completeOrder(sendOutEntity.getPlatformNumber(), getSmCode(sendOutEntity.getTrackId(), sendOutEntity.getCompanyId()),trackCode);
//        if (b1)
//            log.info(String.format("易仓订单%s修改出库状态成功", sendOutEntity.getPlatformNumber()));
        log.info(String.format("易仓订单%s回传完成", sendOutEntity.getPlatformNumber()));

    }

    private String getSmCode(Long trackId, Long companyId) {
        if (companyId.intValue() == 283) {
            if (trackId == 8) {
                return "KDJP_ZC";
            } else if (trackId == DicBusinessItemConstant.yamatoExpress || trackId.equals(DicBusinessItemConstant.yamatoExpressNew) || trackId.equals(DicBusinessItemConstant.yamatoExpressBox) || trackId.equals(DicBusinessItemConstant.yamatoExpressSmall)) {
                return "KDJP_HM";
            }
            return "KDJP_ZC";
        }
        return "";
    }

    @Override
    public List<String> addYahooList(List<OrderOutputAddReq> orderOutputAddReqList, Long userId) {
        List<String> failedOrderids = new ArrayList<>();
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            String value = add(outputAddReq, userId);
            if (value != null) {
                failedOrderids.add(value);
            } else {
                yahooService.updateOrderSendOut(outputAddReq.getOrderNo());
            }
        }
        return failedOrderids;
    }


    @Override
    public void countStorageWorks(long storageId) {
        List<String> dataList = new ArrayList<>();
        dataList.add("2021-04-01");
        dataList.add("2021-05-01");
        dataList.add("2021-06-01");
        dataList.add("2021-07-01");
        dataList.add("2021-08-01");
        dataList.add("2021-09-01");
        dataList.add("2021-10-01");
        dataList.add("2021-11-01");
        dataList.add("2021-12-01");
        dataList.add("2022-01-01");
        dataList.add("2022-02-01");
        dataList.add("2022-03-01");
        dataList.add("2022-04-01");
        dataList.add("2022-05-01");
        dataList.add("2022-06-01");
        dataList.add("2022-07-01");
        List<Map<String, Object>> sheetsList = new ArrayList<>();
        StorageDo storageDo = storageDao.selectById(storageId);
        List<DicBusinessItemDo> dicBusinessItemDos = dicBusinessItemDao.selectList(new LambdaQueryWrapper<DicBusinessItemDo>().eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.trackCompany));
        List<DicBusinessItemDo> fbaItemDos = dicBusinessItemDao.selectList(new LambdaQueryWrapper<DicBusinessItemDo>().eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.fbaOrderOutPutTruck));
        DicBusinessItemDo itemDo = new DicBusinessItemDo();
        itemDo.setId(8L);
        itemDo.setDicItemValue("佐川急便");
        fbaItemDos.add(0, itemDo);
        for (int i = 0; i < dataList.size(); i++) {
            Map map = new HashMap();
            String date = dataList.get(i);
            long totalCount = 0;
            System.out.println("==================" + date + "=======================");

            List<StorageWorksExport> orderInputPickupExcelExportVos = new ArrayList<>();
            for (DicBusinessItemDo dicBusinessItemDo : dicBusinessItemDos) {
                StorageWorksExport oneMap = new StorageWorksExport();
                LambdaQueryWrapper<OrderOutputDo> wrapper = new LambdaQueryWrapper<OrderOutputDo>().eq(OrderOutputDo::getStorageId, storageId).eq(OrderOutputDo::getTrackId, dicBusinessItemDo.getId()).ge(OrderOutputDo::getSendDate, date);
                if (i < dataList.size() - 1) {
                    wrapper.lt(OrderOutputDo::getSendDate, dataList.get(i + 1));
                }
                List<OrderOutputDo> orderOutputDos = dao.selectList(wrapper);
                int companyCount = orderOutputDos.stream().mapToInt(orderOutputDo -> {
                    return productDao.selectList(new LambdaQueryWrapper<OrderOutputProductDo>().eq(OrderOutputProductDo::getOrderId, orderOutputDo.getId())).stream().mapToInt(OrderOutputProductDo::getCount).sum();
                }).sum();
                double money = orderOutputDos.stream().mapToDouble(OrderOutputDo::getShipFee).sum();
                System.out.println(dicBusinessItemDo.getDicItemValue() + "companyCount:" + companyCount);
                System.out.println(dicBusinessItemDo.getDicItemValue() + "money:" + money);
                oneMap.setTrackCompany("toC " + dicBusinessItemDo.getDicItemValue() + "发货数量");
                oneMap.setCount(companyCount);
                oneMap.setPrice(money);
                orderInputPickupExcelExportVos.add(oneMap);
            }
            int packageCount = 0;
            int productCount = 0;

            for (DicBusinessItemDo dicBusinessItemDo : fbaItemDos) {
                int count = 0;
                StorageWorksExport oneMap = new StorageWorksExport();
                LambdaQueryWrapper<FbaOrderOutputDo> wrapper = new LambdaQueryWrapper<FbaOrderOutputDo>().eq(FbaOrderOutputDo::getStorageId, storageId).eq(FbaOrderOutputDo::getTrackId, dicBusinessItemDo.getId()).ge(FbaOrderOutputDo::getSendDate, date);
                if (i < dataList.size() - 1) {
                    wrapper.lt(FbaOrderOutputDo::getSendDate, dataList.get(i + 1));
                }
                List<FbaOrderOutputDo> fbaOrderOutputDos = fbaOrderOutDao.selectList(wrapper);
                double totalPrice = 0;
                double totalSize = 0;
                for (FbaOrderOutputDo fbaOrderOutputDo : fbaOrderOutputDos) {
                    for (FbaOrderOutputPackageDo packageDo : fbaOrderOutputPackageDao.selectList(new LambdaQueryWrapper<FbaOrderOutputPackageDo>().eq(FbaOrderOutputPackageDo::getFbaOrderOutputId, fbaOrderOutputDo.getId()))) {
                        double v = packageDo.getHeight() * packageDo.getWidth() * packageDo.getLength() * packageDo.getCount() / 1000000;
                        totalSize = totalSize + v;
                        if (fbaOrderOutputDo.getFileId() != null) {
                            packageCount = packageCount + packageDo.getCount();
                        }
                        count = count + packageDo.getCount();
                        for (FbaOrderOutputProductDo productDo : fbaOrderOutputProductDao.selectList(new LambdaQueryWrapper<FbaOrderOutputProductDo>().eq(FbaOrderOutputProductDo::getPackageId, packageDo.getId()))) {
                            if (fbaOrderOutputDo.getProductFileId() != null) {
                                productCount = productCount + packageDo.getCount() * productDo.getCount();

                            }
                        }
                    }
                    totalPrice = totalPrice + fbaOrderOutputDo.getShipFee();
                }
                double price = new BigDecimal(totalPrice).setScale(2, BigDecimal.ROUND_UP).doubleValue();
                System.out.println(dicBusinessItemDo.getDicItemValue() + "totalPrice:" + totalPrice);
                System.out.println(dicBusinessItemDo.getDicItemValue() + "totalSize:" + totalSize);
                if (dicBusinessItemDo.getId() == 8) {
                    oneMap.setTrackCompany("toB " + dicBusinessItemDo.getDicItemValue() + "发货箱数");
                    oneMap.setCount(new BigDecimal(count).intValue());
                } else {
                    oneMap.setTrackCompany("toB " + dicBusinessItemDo.getDicItemValue() + "发货体积(m³)");
                    oneMap.setCount(new BigDecimal(totalSize).setScale(1, BigDecimal.ROUND_UP).intValue());
                }
                oneMap.setPrice(price);
                orderInputPickupExcelExportVos.add(oneMap);
            }
            StorageWorksExport oneMap = new StorageWorksExport();
            oneMap.setTrackCompany("大标贴标数");
            oneMap.setCount(new BigDecimal(packageCount).setScale(1, BigDecimal.ROUND_UP).intValue());
            orderInputPickupExcelExportVos.add(oneMap);
            oneMap = new StorageWorksExport();
            oneMap.setTrackCompany("小标贴标数");
            oneMap.setCount(productCount);
            orderInputPickupExcelExportVos.add(oneMap);
            LambdaQueryWrapper<OrderBackDo> ge = new LambdaQueryWrapper<OrderBackDo>().eq(OrderBackDo::getStorageId, storageId).ge(OrderBackDo::getStatus, DicBusinessItemConstant.orderBackFinish).ge(OrderBackDo::getCreateTime, date);
            if (i < dataList.size() - 1) {
                ge.lt(OrderBackDo::getCreateTime, dataList.get(i + 1));
            }
            List<OrderBackDo> orderBackDoList = orderBackService.getBaseMapper().selectList(ge);
            int backOrderCount = orderBackDoList.size();
            oneMap = new StorageWorksExport();
            oneMap.setTrackCompany("退货反馈件数");
            oneMap.setCount(backOrderCount);
            orderInputPickupExcelExportVos.add(oneMap);
            LambdaQueryWrapper<OrderWorkDo> ge1 = new LambdaQueryWrapper<OrderWorkDo>().eq(OrderWorkDo::getStorageId, storageId).ge(OrderWorkDo::getStatus, 2).ge(OrderWorkDo::getCreateTime, date);
            Integer workCount = orderWorkDao.selectCount(ge1);
            if (i < dataList.size() - 1) {
                ge1.lt(OrderWorkDo::getCreateTime, dataList.get(i + 1));
            }
            oneMap = new StorageWorksExport();
            oneMap.setTrackCompany("特殊处理事项数");
            oneMap.setCount(workCount);
            orderInputPickupExcelExportVos.add(oneMap);
            LambdaQueryWrapper<ReplacementDo> ge2 = new LambdaQueryWrapper<ReplacementDo>().eq(ReplacementDo::getOutputStorageId, storageId).ge(ReplacementDo::getStatus, 2).ge(ReplacementDo::getCreateTime, date);
            Integer replaceCount = replacementDao.selectCount(ge2);
            if (i < dataList.size() - 1) {
                ge2.lt(ReplacementDo::getCreateTime, dataList.get(i + 1));
            }
            oneMap = new StorageWorksExport();
            oneMap.setTrackCompany("配件发送件数");
            oneMap.setCount(replaceCount);
            orderInputPickupExcelExportVos.add(oneMap);
            ExportParams orderOutputParams = new ExportParams();
            // 设置sheet得名称
            orderOutputParams.setSheetName(date.substring(0, 7));
            Map<String, Object> orderOutputMap = new HashMap<>();
            // title的参数为ExportParams类型，目前仅仅在ExportParams中设置了sheetName
            orderOutputMap.put("title", orderOutputParams);
            // 模版导出对应得实体类型
            orderOutputMap.put("entity", StorageWorksExport.class);
            // sheet中要填充得数据
            orderOutputMap.put("data", orderInputPickupExcelExportVos);
            sheetsList.add(orderOutputMap);
        }
        try {
            ExcelUtils.exportExcel(sheetsList, templatePath + File.separator + storageDo.getStorageName() + "仓库工作量.xls");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object updateStock(OrderOutputUpdateReq req, Long userId) {
        OrderOutputDo outputDo = dao.selectById(req.getId());
        if (outputDo == null) {
            throw new BizException(SysConstant.Order_NotExist1);
        }
        if (outputDo.getStatus() > DicBusinessItemConstant.outCreateCheckState) {
            throw new BizException(SysConstant.Order_HadDeal);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("storage", storageService.getList(new HashMap<>()));
        map.put("region", regionService.getList(new HashMap<>()));
        HashMap<String, String> map1 = new HashMap<>();
        map1.put("company_id", outputDo.getCompanyId() + "");
        map.put("shopList", shopService.getList(map1));
        OrderOutputDetailRes res = new OrderOutputDetailRes();
        outputDo.setShopId(req.getShopId());
        outputDo.setStorageId(req.getStorageId());
        BeanUtils.copyProperties(outputDo, res);
        map.put("detail", handlerDetailAfter(outputDo, res));
        return SingleResult.success(map);
    }

    /**
     * 批量拣货， 已打单直接出库预览
     *
     * @param req
     * @param userId
     * @param companyId
     * @return
     */
    @Override
    public List<BatchPickUpRes> batchPickUp(BatchPickUpReq req, Long userId, Long companyId) {
        PickUpRes result = this.batchPickUpNotException(req, userId, companyId);
        if (result.getCode() != 200) {
            throw new BizException(result.getMsg(), result.getOrderNo().split("@-"));
        }
        return result.getResList();
    }


    /**
     * 不抛出异常
     *
     * @param req
     * @param userId
     * @param companyId
     * @return
     */
    public PickUpRes batchPickUpNotException(BatchPickUpReq req, Long userId, Long companyId) {
        PickUpRes result = new PickUpRes();
        List<OrderOutputDo> orderList = dao.selectList(new QueryWrapper<OrderOutputDo>().in("id", req.getIds()));
        //计算出包裹性质（一单一件，一单多件）并赋值到字段orderType上  1:一单一件 2:一单多件  表中已有orderType但字段已废弃 现在用来存计算好的包裹性质值
//        for (OrderOutputDo et : orderList) {
//            List<OrderOutputProductDo> productDoList = productDao.selectList(new QueryWrapper<OrderOutputProductDo>().eq("order_id", et.getId()));
//            int sum = productDoList.stream().mapToInt(OrderOutputProductDo::getCount).sum();
//            et.setOrderType(sum >= 2 ? 2 : 1);
//        }

        //判断是一单一件还是一单多件
        List<OrderOutputProductDo> productDoList = orderOutputProductDao.selectList(new LambdaQueryWrapper<OrderOutputProductDo>().in(OrderOutputProductDo::getOrderId, orderList.stream().map(OrderOutputDo::getId).collect(Collectors.toList())));
        Map<Long, List<OrderOutputProductDo>> productMapList = productDoList.stream().collect(Collectors.groupingBy(OrderOutputProductDo::getOrderId));

        Map<String, List<OrderOutputDo>> mapList;
//        StockPickUpRuleDo ruleDo = stockPickUpRuleDao.selectOne(new LambdaQueryWrapper<StockPickUpRuleDo>().last(" order by id desc limit 1"));
//        if (ruleDo == null) {
//            throw new BizException(SysConstant.No_Data);
//        }
//        if (ruleDo == null) {
//            //将查出来的list 按仓库id、快递id、包裹性质（一单一件，一单多件）分组
//            mapList = orderList.stream().collect(Collectors.groupingBy(outputDo -> outputDo.getStorageId()+""));
//        }
//        else {
        mapList = stockPickUpService.getOrderMapList(orderList, productMapList);
//        }
//
        //遍历map取list
        List<BatchPickUpRes> pickUpList = new ArrayList<>();
        for (String key : mapList.keySet()) {
            List<OrderOutputDo> orderOutputList = mapList.get(key);
            //map是遍历后的 就是已经根据那三个字段分类过的 取第一条的 然后在循环该map下插入
            Long storageId = orderOutputList.get(0).getStorageId();

            BatchPickUpRes res = new BatchPickUpRes();

            StorageDo storageDo = storageDao.selectById(storageId);
            if (storageDo == null) {
                result.setCode(500);
                result.setMsg(SysConstant.Storage_NotExist);
                return result;
            }
            res.setStorageName(storageDo.getStorageName());
            res.setStorageId(storageId);

            List<PositionAndNumberDTO> positionAndNumberList = new ArrayList<>();
            List<PositionAndNumberDTO> defaultPositionList = new ArrayList<>();

            StockPickUpRuleDo ruleDo = stockPickUpRuleDao.selectOne(new LambdaQueryWrapper<StockPickUpRuleDo>().eq(StockPickUpRuleDo::getStorageId, storageId).last(" order by id desc limit 1"));

            SendRes sendRes = stockPickUpService.getPositionList(orderOutputList, productMapList, positionAndNumberList, defaultPositionList, ruleDo);
            if (sendRes.getCode() != 200) {
                throw new BizException(sendRes.getMsg());
            }

            int track = ruleDo.getTrack();
            int company = ruleDo.getCompany();
            int area = ruleDo.getArea();
            int packageType = ruleDo.getPackageType();
            int outType = ruleDo.getOutType();
            int sizeType = ruleDo.getSizeType();
            int sku = ruleDo.getSku();
            StringBuilder trackName = new StringBuilder();
            StringBuilder otherRule = new StringBuilder();
            for (int i = 0; i < key.split("@").length; i++) {
                if (i == 0) {
                    //第一个是仓库
                    continue;
                }
                String s = key.split("@")[i];
                if (track == 1) {
                    //按快递公司分
                    if (trackName.length() > 0) {
                        trackName.append(",");
                    }
                    trackName.append(dicBusinessItemService.getDicItemValue(Long.parseLong(s)));
                    res.setTrackId(Long.parseLong(s));
                    track = 0;
                    continue;
                }
                if (company == 1) {
                    //按客户
                    CompanyDo companyDo = companyDao.selectById(Long.parseLong(s));
                    if (companyDo != null) {
                        if (otherRule.length() > 0) {
                            otherRule.append(",");
                        }
                        otherRule.append(companyDo.getCompanyCode());
                    }
                    company = 0;
                    continue;
                }
                if (area == 1) {
                    //地区
                    if (otherRule.length() > 0) {
                        otherRule.append(",");
                    }
                    if ("9".equals(s)) {
                        //关东
                        otherRule.append("关东地区");
                    } else {
                        //其他
                        otherRule.append("其他地区");
                    }
                    area = 0;
                    continue;
                }
                if (packageType == 1) {
                    //包裹类型 2 一单多件 1一单一件
                    if (otherRule.length() > 0) {
                        otherRule.append(",");
                    }
                    otherRule.append("2".equals(s) ? "一单多件" : "一单一件");
                    res.setOrder_ype("2".equals(s) ? 2 : 1);
                    res.setOrderType("2".equals(s) ? "一单多件" : "一单一件");
                    packageType = 0;
                    continue;
                }
                if (outType == 1) {
                    //先进先出 只针对一单一件 1 先进先出 0 不是先进先出
                    if (otherRule.length() > 0) {
                        otherRule.append(",");
                    }
                    otherRule.append("1".equals(s) ? "先进先出" : "非先进先出");
                    outType = 0;
                    continue;
                }
                if (sizeType == 1) {
                    //大小件 只针对一单一件 1 大件 0 小件
                    if (otherRule.length() > 0) {
                        otherRule.append(",");
                    }
                    otherRule.append("1".equals(s) ? "大件" : "小件");
                    sizeType = 0;
                    continue;
                }
                if (sku == 1) {
                    //按sku 只针对一单一件
                    if (otherRule.length() > 0) {
                        otherRule.append(",");
                    }
                    otherRule.append("0".equals(s) ? "不按sku" : "按sku");
                    sku = 0;
                    continue;
                }
            }
            res.setTrackName(trackName.toString());
            res.setOtherRule(otherRule.toString());
//            res.setOrder_ype(packageType);
            res.setRuleId(ruleDo.getId());

            String otherRuleStr = otherRule.toString();
            BatchPickUpRes defaultRes = new BatchPickUpRes();//默认库位 得 返回值
            BeanUtils.copyProperties(res, defaultRes);
            if (positionAndNumberList.size() > 0) {
                Map<Long, List<PositionAndNumberDTO>> positionMap = positionAndNumberList.stream().collect(Collectors.groupingBy(PositionAndNumberDTO::getOrderOutputId));
                res.setPositionAndNumberList(positionAndNumberList);
                if (ruleDo.getDefaultRack() == 1) {
                    res.setOtherRule(res.getOtherRule() + (StringUtils.isNotBlank(res.getOtherRule()) ? "," : "") + "非默认库位");
                }
                if (res.getTrackId() == null) {
                    Set<Long> trackId = new HashSet<>();
                    for (OrderOutputDo e : orderOutputList) {
                        if (positionMap.get(e.getId()) != null) {
                            trackId.add(e.getTrackId());
                        }
                    }
                    if (trackId.size() == 1) {
                        res.setTrackId(orderOutputList.get(0).getTrackId());
                        res.setTrackName(dicBusinessItemService.getDicItemValue(res.getTrackId()));
                    }
                }

                pickUpList.add(res);
            }

            if (defaultPositionList.size() > 0) {
                Map<Long, List<PositionAndNumberDTO>> positionMap = defaultPositionList.stream().collect(Collectors.groupingBy(PositionAndNumberDTO::getOrderOutputId));

                defaultRes.setPositionAndNumberList(defaultPositionList);
                if (ruleDo.getDefaultRack() == 1) {
                    defaultRes.setOtherRule(otherRuleStr + (StringUtils.isNotBlank(otherRuleStr) ? "," : "") + "默认库位");
                }
                if (defaultRes.getTrackId() == null) {
                    Set<Long> trackId = new HashSet<>();
                    for (OrderOutputDo e : orderOutputList) {
                        if (positionMap.get(e.getId()) != null) {
                            trackId.add(e.getTrackId());
                        }
                    }
                    if (trackId.size() == 1) {
                        defaultRes.setTrackId(orderOutputList.get(0).getTrackId());
                        defaultRes.setTrackName(dicBusinessItemService.getDicItemValue(res.getTrackId()));
                    }
                }
                pickUpList.add(defaultRes);
            }

        }

        if (pickUpList.size() > 0) {
            for (BatchPickUpRes batchPickUpRes : pickUpList) {
                batchPickUpRes.setShowList(stockPickUpService.getShowList(batchPickUpRes.getPositionAndNumberList()));
            }
        }
        result.setCode(200);
        result.setResList(pickUpList);
        return result;

    }


    @Override
    public SingleResult batchPickUpConfirm(BatchPickUpConfirmReq req, Long userId, Long companyId) {
        List<String> successList = new ArrayList<>();
        List<Long> ids = new ArrayList<>();
        for (BatchPickUpRes res : req.getPickUpList()) {
            //判断出库单
            List<Long> orderIdList = res.getPositionAndNumberList().stream().map(PositionAndNumberDTO::getOrderOutputId).collect(Collectors.toList());
            if (orderIdList.size() == 0) {
                continue;
            }
            List<FbaOrderOutputDo> fbaList = new ArrayList<>();
            List<OrderOutputDo> outputList = new ArrayList<>();
            if (req.getType() != null && req.getType() == 1) {
                //Fba
                fbaList = fbaOrderOutDao.selectBatchIds(orderIdList);
                for (FbaOrderOutputDo et : fbaList) {
                    if (!DicBusinessItemConstant.fbaOrderCheckStatus.equals(et.getStatus()) && !DicBusinessItemConstant.fbaOrderPrintStatus.equals(et.getStatus()) && !DicBusinessItemConstant.fbaOrderAppointStorageStatus.equals(et.getStatus()) && !DicBusinessItemConstant.fbaOrderAppointCarStatus.equals(et.getStatus())) {
                        throw new BizException(SysConstant.FbaOrder_Pickup_Status_Error1, et.getFbaOrderOutputNumber());
                    }
                    this.checkPickUp(et.getId(), et.getPickUpId(), et.getFbaOrderOutputNumber(), userId);
                }
            } else {
                //orderOutput
                outputList = dao.selectBatchIds(orderIdList);
                for (OrderOutputDo et : outputList) {
                    if (!(DicBusinessItemConstant.outCreateCheckState.equals(et.getStatus()) || (DicBusinessItemConstant.outWaitSendOut.equals(et.getStatus()) && et.getPickUpId() == null))) {
                        if (DicBusinessItemConstant.outWaitSendOut.equals(et.getStatus()) && et.getPickUpId() != null) {
                            throw new BizException(SysConstant.FbaOrder_Pickup_Status_Error3, et.getOrderOutputNumber());
                        } else if (!DicBusinessItemConstant.outCreateCheckState.equals(et.getStatus())) {
                            throw new BizException(SysConstant.FbaOrder_Pickup_Status_Error4, et.getOrderOutputNumber());
                        }
                    }
                    this.checkPickUp(et.getId(), et.getPickUpId(), et.getOrderNo(), userId);
                }
            }


            //保存到拣货表
            StockPickUpDo pickUpDo = new StockPickUpDo();
            String pickUpNum = DateFormater.formatMillionSecond(new Date());
            //检查pickNumber是否重复
            int count = stockPickUpDao.selectCount(new QueryWrapper<StockPickUpDo>().eq("pick_up_number", "JH" + pickUpNum));
            if (count > 0) {
                //从第二位开始截取
                Long num = Long.valueOf(pickUpNum);
                //重复加一
                pickUpDo.setPickUpNumber("JH" + (num + 1));
            } else {
                pickUpDo.setPickUpNumber("JH" + pickUpNum);
            }

            pickUpDo.setCompanyId(companyId);
            pickUpDo.setStatus(0);
            if (req.getType() != null && req.getType() == 1) {
                pickUpDo.setType("fbaOutput");
            } else {
                pickUpDo.setType("output");
            }
            pickUpDo.setStorageId(res.getStorageId());
            pickUpDo.setTrackId(res.getTrackId());
            pickUpDo.setOrderType(res.getOrder_ype());
            pickUpDo.setOtherRule(res.getOtherRule());
            pickUpDo.setCreateBy(userId);
            pickUpDo.setCreateTime(new Date());
            stockPickUpDao.insert(pickUpDo);

            Map<Long, List<OrderOutputDo>> outputMapList = outputList.stream().collect(Collectors.groupingBy(OrderOutputDo::getId));
            Map<Long, List<FbaOrderOutputDo>> fbaOutputMapList = fbaList.stream().collect(Collectors.groupingBy(FbaOrderOutputDo::getId));

            Map<String, List<PositionAndNumberDTO>> listMapT = res.getPositionAndNumberList().stream().collect(Collectors.groupingBy(i -> i.getStorageId() + "_" + i.getProductId() + "_" + i.getRackId()));

            List<PositionAndNumberDTO> oldShowList = stockPickUpService.getShowList(res.getPositionAndNumberList());
            if (oldShowList.size() != res.getShowList().size()) {
                throw new BizException(SysConstant.StockPickup_Quantity_Error);
            }
            for (int i = 0; i < res.getShowList().size(); i++) {
                List<PositionAndNumberDTO> list = listMapT.get(oldShowList.get(i).getStorageId() + "_" + oldShowList.get(i).getProductId() + "_" + oldShowList.get(i).getRackId());
                for (PositionAndNumberDTO positionAndNumberDTO : list) {
                    positionAndNumberDTO.setRackId(res.getShowList().get(i).getRackId());
                }
            }
            //先将出库单 按仓库-产品 的 分类
            Map<String, List<PositionAndNumberDTO>> listMap = res.getPositionAndNumberList().stream().collect(Collectors.groupingBy(i -> i.getStorageId() + "_" + i.getProductId() + "_" + i.getRackId()));

            List<PositionAndNumberDTO> positionAndNumberList = new ArrayList<>();
            //重新获取 positionAndNumberList
            for (PositionAndNumberDTO showDto : res.getShowList()) {
                ProductInfoDo productInfoDo = productInfoDao.selectObject(showDto.getProductId());
                if (productInfoDo == null) {
                    throw new BizException(SysConstant.Product_NotExist);
                }
                StoragePositionDo positionDo = storagePositionDao.selectById(showDto.getRackId());
                StorageDo storageDo = storageDao.selectById(showDto.getStorageId());
                Map<String, String> map = new HashMap<>();
                map.put("productId", showDto.getProductId() + "");
                map.put("storageId", showDto.getStorageId() + "");
                if (showDto.getRackId() != null) {
                    map.put("rackId", showDto.getRackId() + "");
                } else {
                    map.put("default", "1");
                }
                List<PickupStockRackDto> stockRackList;
                //倒序获取库位货存 可做到先进先出
                synchronized (this) {
                    stockRackList = productStockRackDao.getStockRackBySort(map);
                }

                List<PositionAndNumberDTO> storageProductList = listMap.get(showDto.getStorageId() + "_" + showDto.getProductId() + "_" + showDto.getRackId());
                if (storageProductList == null) {
                    throw new BizException(SysConstant.No_Data);
                }
                if (storageProductList.stream().mapToInt(PositionAndNumberDTO::getNumber).sum() != showDto.getNumber()) {
                    throw new BizException(SysConstant.No_Data);
                }
                //记录 这个仓库这个商品 每个出库单有多少个
                Map<Long, Integer> orderCountMap = new HashMap<>();
                for (PositionAndNumberDTO positionAndNumberDTO : storageProductList) {
                    orderCountMap.merge(positionAndNumberDTO.getOrderOutputId(), positionAndNumberDTO.getNumber(), Integer::sum);
                }
                for (Long orderId : orderCountMap.keySet()) {

                    int goodQuantity = orderCountMap.get(orderId);
                    if (stockRackList.size() <= 0) {
                        throw new BizException(SysConstant.StockPickup_Finish_Error, productInfoDo.getCommoditySku(), positionDo == null ? "默认库位" : positionDo.getPositionName(), goodQuantity);
                    }
                    for (PickupStockRackDto st : stockRackList) {
                        if (st.getGoodQuantity() <= 0) {
                            continue;
                        }
                        goodQuantity = stockPickUpService.getPositionAndNumberDTO(positionAndNumberList, st, productInfoDo, storageDo, goodQuantity, orderId);
                        if (goodQuantity <= 0) {
                            break;
                        }
                    }
                    if (goodQuantity > 0) {
                        throw new BizException(SysConstant.StockPickup_Finish_Error, productInfoDo.getCommoditySku(), positionDo == null ? "默认库位" : positionDo.getPositionName(), goodQuantity);
                    }
                }

            }


            //修改过需求，拣货预览时，库位可以选择修改 此时 showList是更新过的库位id 但是 positionAndNumberList rackId是没有更新过的
            for (PositionAndNumberDTO positionAndNumberDTO : positionAndNumberList) {
                //根据商品 和 仓库 获取最新 stockRackId

                //添加到拣货详情表
                StockPickUpDetailDo pickUpDetailDo = new StockPickUpDetailDo();
                pickUpDetailDo.setPickUpId(pickUpDo.getId());
                pickUpDetailDo.setProductId(positionAndNumberDTO.getProductId());
                pickUpDetailDo.setStockRackId(positionAndNumberDTO.getStockRackId());
                pickUpDetailDo.setNumber(positionAndNumberDTO.getNumber());
                pickUpDetailDo.setOrderOutputId(positionAndNumberDTO.getOrderOutputId());
                stockPickUpDetailDao.insert(pickUpDetailDo);

                ProductStockFlowingDo flowingDo = new ProductStockFlowingDo();
                String flowingNoteNo = null;
                Long flowingCompanyId = null;
                Long flowingShopId = null;
                String flowingTips = null;
                if ("output".equals(pickUpDo.getType())) {
//                OrderOutputDo outputDo = dao.selectById(positionAndNumberDTO.getOrderOutputId());
                    if (outputMapList.get(positionAndNumberDTO.getOrderOutputId()) == null || outputMapList.get(positionAndNumberDTO.getOrderOutputId()).size() < 1) {
                        throw new BizException(SysConstant.OrderOutput_NotMatch);
                    }
                    OrderOutputDo outputDo = outputMapList.get(positionAndNumberDTO.getOrderOutputId()).get(0);
                    flowingNoteNo = outputDo.getOrderOutputNumber();
                    flowingCompanyId = outputDo.getCompanyId();
                    flowingShopId = outputDo.getShopId();
                    flowingTips = "出库单拣货,锁定库存";

                } else if ("fbaOutput".equals(pickUpDo.getType())) {
//                    FbaOrderOutputDo fbaOutput = fbaOrderOutDao.selectById(positionAndNumberDTO.getOrderOutputId());
                    if (fbaOutputMapList.get(positionAndNumberDTO.getOrderOutputId()) == null || fbaOutputMapList.get(positionAndNumberDTO.getOrderOutputId()).size() < 1) {
                        throw new BizException(SysConstant.OrderOutput_NotMatch_Fba);
                    }
                    FbaOrderOutputDo fbaOutput = fbaOutputMapList.get(positionAndNumberDTO.getOrderOutputId()).get(0);
                    flowingNoteNo = fbaOutput.getFbaOrderOutputNumber();
                    flowingCompanyId = fbaOutput.getCompanyId();
                    flowingShopId = fbaOutput.getShopId();
                    flowingTips = "fba出库单拣货,锁定库存";
                } else {
                    throw new BizException(SysConstant.StockPickup_Type_NotMatch);
                }
                ProductStockRackDo racKDo;
                synchronized (this) {
                    racKDo = productStockRackDao.selectById(positionAndNumberDTO.getStockRackId());
                }
                //锁定库存前 判断货位库存量是否足够
                if (positionAndNumberDTO.getNumber() <= racKDo.getGoodQuantity()) {
                    racKDo.setGoodQuantity(racKDo.getGoodQuantity() - positionAndNumberDTO.getNumber());
                    racKDo.setGoodLockQuantity(racKDo.getGoodLockQuantity() + positionAndNumberDTO.getNumber());
                    productStockRackDao.updateById(racKDo);
                    //库存流水
                    productStockFlowingService.insertFlowing(pickUpDo.getType(), flowingNoteNo, flowingShopId, positionAndNumberDTO.getProductId(), pickUpDo.getStorageId(), -positionAndNumberDTO.getNumber(), 0, positionAndNumberDTO.getNumber(), racKDo.getRackId(), flowingCompanyId, userId, flowingTips);
                } else {
                    ProductInfoDo productInfoDo = productInfoDao.selectById(positionAndNumberDTO.getProductId());
                    if (productInfoDo == null) {
                        throw new BizException(SysConstant.Product_NotExist);
                    }
                    StoragePositionDo positionDo = storagePositionDao.selectById(racKDo.getRackId());
                    throw new BizException(SysConstant.StockPickup_Finish_Error, productInfoDo.getCommoditySku(), positionDo == null ? "默认库位" : positionDo.getPositionName(), positionAndNumberDTO.getNumber() - racKDo.getGoodQuantity());
//                throw new BizException("sku:" + productInfoDo.getCommoditySku() + " 库位:" + positionDo.getPositionName() + "库存不足，缺少：" + (positionAndNumberDTO.getNumber() - racKDo.getGoodQuantity()) + "件");
                }
            }


            //出库单/fba出库单关联拣货表id
            if (fbaList.size() > 0) {
                for (FbaOrderOutputDo et : fbaList) {
                    et.setPickUpId(pickUpDo.getId());
                    et.setPickStatus(StaticDict.Pick_Up_Status.UnPick.getValue());
//                    fbaOutputDo.setStatus(DicBusinessItemConstant.fbaWaitingPickUp);
                    et.setUpdateTime(new Date());
                    et.setUpdateBy(userId);
                    fbaOrderOutDao.updateById(et);
                }

            } else if (outputList.size() > 0) {
                for (OrderOutputDo et : outputList) {
                    et.setPickUpId(pickUpDo.getId());
                    et.setStatus(DicBusinessItemConstant.waitingPickUp);
                    et.setUpdateTime(new Date());
                    et.setUpdateBy(userId);
                    dao.updateById(et);
                }
            } else {
                throw new BizException(SysConstant.OrderOutput_NotMatch);
            }

            successList.add(String.format(StringsUtil.createI18Message(SysConstant.OrderOutput_Pickup_Success), pickUpDo.getPickUpNumber()));
            ids.add(pickUpDo.getId());
        }
        SingleResult singleResult = new SingleResult();
        singleResult.setCode("200");
        singleResult.setData(successList);
        Map map = new HashMap();
        map.put("ids", ids);
        singleResult.setMapInfo(map);
        return singleResult;
    }

    @Override
    public void sendYamatoSizeMail() {
        List<OrderOutputYamatoSizeExcelExportVo> collect = getYamatoSizeExcel(new HashMap<>(), null, null);
        String title = "" + TimeUtils.getCurrentDateFormat("M月d日") + "東之和合同会社送り状番号サイズ情報の送信";
        String cotent = "ヤマト運輸株式会社<br>" + "<br>" + "ご担当者様<br>" + "<br>" + "いつもお世話になっております。<br>" + "<br>" + TimeUtils.getCurrentDateFormat("M月d日") + "分の東之和合同会社送り状番号サイズ情報を添付しております。<br>" + "<br>" + "ご確認のほどよろしくお願いいたします。<br>" + "<br>" + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + "東之和合同会社";
        String address = "00809461@kuronekoyamato.co.jp";
        String cc = "y1356001@kuronekoyamato.co.jp,00132096@kuronekoyamato.co.jp,y4295601@kuronekoyamato.co.jp,service@cloudkinto.com,sakagami@sanchoum.com";
//        String address = "770403372@qq.com";
//        String cc = "770403372@qq.com,zjp@cloudkinto.com,lin@cloudkinto.com";
        String fileName = TimeUtils.getCurrentDateFormat() + "Yamato出荷サイズ.csv";

        Session session = mailSenderService.initMailSession();
        Transport transport = mailSenderService.initMailTransport(session);
        CsvExportParams exportParams2 = new CsvExportParams();
        exportParams2.setCreateHeadRows(true);
        exportParams2.setEncoding("Shift-JIS");
        CsvUtils.exportCsv(exportParams2, OrderOutputYamatoSizeExcelExportVo.class, collect, fileName, filePath);

        String finalTitle = title;
        String finalContent = cotent;
        String finalCc = cc;
        String finalAddress = address;
        String finalFileName = fileName;
        threadPoolTaskExecutor.execute(() -> {
            mailSenderService.sendFileEmail(session, transport, finalTitle, TimeUtils.getCurrentDateFormat() + "出荷サイズ.csv", finalContent, "text/html;charset=Shift-JIS", finalAddress, finalCc, filePath + File.separator + finalFileName);

        });
    }

    @Override
    public void exportYamatoSizeExcel(Map<String, String> map, List<Long> ids, HttpServletResponse response) {
        List<OrderOutputYamatoSizeExcelExportVo> collect = getYamatoSizeExcel(map, ids, response);
        try {
            ExcelUtils.exportExcel(collect, OrderOutputYamatoSizeExcelExportVo.class, TimeUtils.getCurrentDateFormat() + "Yamato出荷サイズ.xls", new ExportParams(), response);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private List<OrderOutputYamatoSizeExcelExportVo> getYamatoSizeExcel(Map<String, String> map, List<Long> ids, HttpServletResponse response) {
        if (ids == null) ids = new ArrayList<>();
        final List<Long> orderIdsList = ids;
        if (orderIdsList.size() < 1) {
            List<OrderOutputDo> orderList = dao.selectYamatoSize();
            if (orderList == null) {
                throw new BizException(SysConstant.No_Data);
            }
            orderList.stream().forEach(orderOutputDo -> {
                orderIdsList.add(orderOutputDo.getId());
            });
        }
        List<OrderOutputYamatoSizeExcelExportVo> sizeExcelExportVos = new ArrayList<>();
        List<DimensDo> dimensDos = mDimenDao.selectList(new LambdaQueryWrapper<DimensDo>().eq(DimensDo::getTrackId, DicBusinessItemConstant.yamatoExpress));
        List<OrderOutputYamatoSizeExcelExportDto> orderOutputYamatoSizeExcelExportDtos = dao.selePackageNumberAndSize(orderIdsList);
        List<OrderOutputYamatoSizeExcelExportVo> collect = orderOutputYamatoSizeExcelExportDtos.stream().map(new Function<OrderOutputYamatoSizeExcelExportDto, OrderOutputYamatoSizeExcelExportVo>() {
            @Override
            public OrderOutputYamatoSizeExcelExportVo apply(OrderOutputYamatoSizeExcelExportDto yamatoSizeExcelExportDto) {
                OrderOutputYamatoSizeExcelExportVo excelExportVo1 = new OrderOutputYamatoSizeExcelExportVo();
                excelExportVo1.setTrackNumber(yamatoSizeExcelExportDto.getTrackNumber());
                for (DimensDo dimensDo : dimensDos) {
                    if (dimensDo.getVolume() > yamatoSizeExcelExportDto.getSize()) {
                        excelExportVo1.setSize(dimensDo.getVolume().intValue());
                        break;
                    }
                }
//                BeanConvert.INSTANCE.yamatoSizeDto2ExportVo(orderOutputYamatoSizeExcelExportDto,excelExportVo1);
                return excelExportVo1;
            }
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 检查 拣货单 是否有子集
     *
     * @param orderId
     * @param pickUpId
     * @param orderNo
     */
    public void checkPickUp(Long orderId, Long pickUpId, String orderNo, Long userId) {
        //在判断是否关联了 拣货单， 如果拣货单 已拣货 不可再次拣货， 如果拣货单 未拣货 ，需要删除 旧拣货单
        if (pickUpId != null) {
            StockPickUpDo pickUpDo = stockPickUpDao.selectById(pickUpId);
            if (pickUpDo != null && pickUpDo.getStatus() == 1) {
                //已拣货 报错
                throw new BizException(SysConstant.FbaOrder_Pickup_Status_Error2, orderNo, pickUpDo.getPickUpNumber());
            } else if (pickUpDo != null && pickUpDo.getStatus() == 0) {
                //未拣货 先取消拣货单
                UpdatePickUpReq req = new UpdatePickUpReq();
                req.setId(pickUpId);
                req.setStatus(0);
                stockPickUpService.update(req, userId);
//                stockPickUpService.deletePickUp(pickUpId, orderId);
            }
        }
    }

    private String getTrackCode(Long trackId) {
        DicBusinessItemDo itemDo = dicBusinessItemDao.selectById(trackId);
        if (trackId == DicBusinessItemConstant.sagawaExpress) {
            return "佐川急便";
        } else if (trackId == DicBusinessItemConstant.yamatoExpress || trackId.equals(DicBusinessItemConstant.yamatoExpressNew) || trackId.equals(DicBusinessItemConstant.yamatoExpressBox) || trackId.equals(DicBusinessItemConstant.yamatoExpressSmall)) {
            return "ヤマト宅急便";
        } else if (trackId == DicBusinessItemConstant.xinongExpress) {
            return "西濃運輸";
        } else if (trackId == DicBusinessItemConstant.jpostExpress || trackId == DicBusinessItemConstant.jpostExpressCom || trackId == DicBusinessItemConstant.jpostExpressCod) {
            return "クリックポスト";
        } else if (itemDo != null) {
            return itemDo.getDicItemValue();
        }
        return null;
    }


    @Override
    public void setOrderTypeSync() {
        List<OrderOutputDo> list = dao.selectList(new LambdaQueryWrapper<OrderOutputDo>().ge(OrderOutputDo::getCreateTime, DateUtils.dateFormatToString(DateUtils.passingDate(new Date(), -180))));
        for (OrderOutputDo et : list) {
            List<OrderOutputProductDo> productList = orderOutputProductDao.selectList(new LambdaQueryWrapper<OrderOutputProductDo>().eq(OrderOutputProductDo::getOrderId, et.getId()));
            if (productList.size() == 0) {
                et.setOrderType(1);
            } else {

                int count = 0;
                for (OrderOutputProductDo orderOutputProductDo : productList) {
                    count += orderOutputProductDo.getCount();
                }
                et.setOrderType(count > 1 ? 2 : 1);
            }
            dao.updateById(et);
        }
    }

    @Override
    public List<String> addQoo10List(List<OrderOutputAddReq> orderOutputAddReqList, Long currentUserId) {
        List<String> failedOrderids = new ArrayList<>();
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            String value = add(outputAddReq, currentUserId);
            if (value != null) {
                failedOrderids.add(value);
            } else {
                if (StringUtils.isNotBlank(outputAddReq.getOrderNo())) {
                    orderQoo10Sercie.updateOrderSendOut(outputAddReq.getOrderNo());
                }
            }
        }
        return failedOrderids;
    }


    @Override
    public void cancelOrderByOrderId(String platform, List<String> cancelOrderIds) {
        List<OrderOutputDo> orderOutputDoList = dao.selectList(new LambdaQueryWrapper<OrderOutputDo>().eq(OrderOutputDo::getPlatform, platform).eq(OrderOutputDo::getCreateBy, 1L).in(OrderOutputDo::getPlatformNumber, cancelOrderIds));
        for (OrderOutputDo orderOutputDo : orderOutputDoList) {
            if (orderOutputDo.getStatus() >= DicBusinessItemConstant.outCreateCheckState && orderOutputDo.getStatus() < DicBusinessItemConstant.outSendOut || orderOutputDo.getStatus().equals(DicBusinessItemConstant.waitingPickUp) || orderOutputDo.getStatus().equals(DicBusinessItemConstant.alreadyPickUp) || orderOutputDo.getStatus().equals(DicBusinessItemConstant.outToCheck)) {
                orderOutputDo.setStatus(DicBusinessItemConstant.orderCutOff);
                dao.updateById(orderOutputDo);
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_CUTOFF_ORDER, orderOutputDo.getId(), 1L, 3);
            }
        }
    }

    @Override
    public void cancelOrderByRakutenOrderId(List<String> cancelOrderIds) {
        cancelOrderByOrderId("rakuten", cancelOrderIds);
    }
}
